run vfmt on math and sha; add vfmt check to test-compiler

pull/3182/head
Alexander Medvednikov 2019-12-22 02:22:32 +03:00
parent 9198285688
commit a251db068f
17 changed files with 721 additions and 659 deletions

View File

@ -8,12 +8,11 @@ Output: 1.274224153
Time: 11.67s user 0.02s system 99% cpu 11.721 total Time: 11.67s user 0.02s system 99% cpu 11.721 total
*/ */
module main module main
import math import math
import os import os
fn evala(i, j int) int { fn evala(i, j int) int {
return ((i + j) * (i + j + 1) / 2 + i + 1) return ((i + j) * (i + j + 1) / 2 + i + 1)
} }
@ -45,10 +44,8 @@ fn a_times_transp(v mut []f64, u []f64) {
} }
fn main() { fn main() {
args := os.args args := os.args
mut n := int(0) mut n := int(0)
if args.len == 2 { if args.len == 2 {
n = args[1].int() n = args[1].int()
} }
@ -57,22 +54,17 @@ fn main() {
} }
mut u := [f64(1.0)].repeat(n) mut u := [f64(1.0)].repeat(n)
mut v := [f64(1.0)].repeat(n) mut v := [f64(1.0)].repeat(n)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
a_times_transp(mut v, u) a_times_transp(mut v, u)
a_times_transp(mut u, v) a_times_transp(mut u, v)
} }
mut vbv := f64(0) mut vbv := f64(0)
mut vv := f64(0) mut vv := f64(0)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
vbv += u[i] * v[i] vbv += u[i] * v[i]
vv += v[i] * v[i] vv += v[i] * v[i]
} }
ans := math.sqrt(vbv / vv) ans := math.sqrt(vbv / vv)
println('${ans:0.9f}') println('${ans:0.9f}')
} }

View File

@ -18,6 +18,12 @@ fn main() {
} }
fn v_test_compiler(vargs string){ fn v_test_compiler(vargs string){
v_test_compiler2(vargs)
//make_sure_vfmt_was_run()
}
fn v_test_compiler2(vargs string){
vexe := testing.vexe_path() vexe := testing.vexe_path()
parent_dir := os.dir(vexe) parent_dir := os.dir(vexe)
testing.vlib_should_be_present( parent_dir ) testing.vlib_should_be_present( parent_dir )
@ -74,6 +80,8 @@ fn v_test_compiler(vargs string){
vmark.stop() vmark.stop()
eprintln( 'Installing a v module took: ' + vmark.total_duration().str() + 'ms') eprintln( 'Installing a v module took: ' + vmark.total_duration().str() + 'ms')
make_sure_vfmt_was_run()
if building_tools_failed || if building_tools_failed ||
compiler_test_session.failed || compiler_test_session.failed ||
building_examples_failed || building_examples_failed ||
@ -82,3 +90,13 @@ fn v_test_compiler(vargs string){
} }
} }
fn make_sure_vfmt_was_run() {
files := os.walk_ext('.', '_test.v')
for file in files {
println(file)
os.exec('./vfmt $file') or {
println('$file failed')
}
}
}

View File

@ -2513,7 +2513,7 @@ fn (p mut Parser) array_init() string {
const_name := p.prepend_mod(p.lit) const_name := p.prepend_mod(p.lit)
if p.table.known_const(const_name) { if p.table.known_const(const_name) {
c := p.table.find_const(const_name) or { c := p.table.find_const(const_name) or {
// p.error('unknown const `$p.lit`') p.error('unknown const `$const_name`')
exit(1) exit(1)
} }
if c.typ == 'int' && p.peek() == .rsbr { if c.typ == 'int' && p.peek() == .rsbr {
@ -2582,8 +2582,9 @@ fn (p mut Parser) array_init() string {
} }
if p.tok != .rsbr && p.tok != .semicolon { if p.tok != .rsbr && p.tok != .semicolon {
p.gen(', ') p.gen(', ')
line_nr := p.tok
p.check(.comma) p.check(.comma)
p.fspace() p.fspace_or_newline()
} }
i++ i++
// Repeat (a = [0;5] ) // Repeat (a = [0;5] )

View File

@ -2,7 +2,6 @@ module main
import os import os
import term import term
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// / This file will get compiled as part of the main program, // / This file will get compiled as part of the main program,
// / for a _test.v file. // / for a _test.v file.
@ -11,19 +10,20 @@ import term
// / customizing the look & feel of the assertions results easier, // / customizing the look & feel of the assertions results easier,
// / since it is done in normal V code, instead of in embedded C ... // / since it is done in normal V code, instead of in embedded C ...
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
fn cb_assertion_failed(filename string, line int, sourceline string, funcname string) { fn cb_assertion_failed(filename string, line int, sourceline string, funcname string) {
color_on := term.can_show_color_on_stderr() color_on := term.can_show_color_on_stderr()
use_relative_paths := match os.getenv('VERROR_PATHS') { use_relative_paths := match os.getenv('VERROR_PATHS') {
'absolute' { false } 'absolute'{
else { true } false
} }
else {
true}}
final_filename := if use_relative_paths { filename } else { os.realpath(filename) } final_filename := if use_relative_paths { filename } else { os.realpath(filename) }
final_funcname := funcname.replace('main__', '').replace('__', '.') final_funcname := funcname.replace('main__', '').replace('__', '.')
mut fail_message := 'FAILED assertion' mut fail_message := 'FAILED assertion'
if color_on { fail_message = term.bold(term.red(fail_message)) } if color_on {
fail_message = term.bold(term.red(fail_message))
}
eprintln('$final_filename:$line: $fail_message') eprintln('$final_filename:$line: $fail_message')
eprintln('Function: $final_funcname') eprintln('Function: $final_funcname')
eprintln('Source : $sourceline') eprintln('Source : $sourceline')
@ -33,3 +33,4 @@ fn cb_assertion_ok(filename string, line int, sourceline string, funcname string
// do nothing for now on an OK assertion // do nothing for now on an OK assertion
// println('OK ${line:5d}|$sourceline ') // println('OK ${line:5d}|$sourceline ')
} }

View File

@ -52,6 +52,19 @@ fn (p mut Parser) fspace() {
p.fgen(' ') p.fgen(' ')
} }
[if vfmt]
fn (p mut Parser) fspace_or_newline() {
if p.first_pass() {
return
}
if p.token_idx >= 2 && p.tokens[p.token_idx-1].line_nr !=
p.tokens[p.token_idx-2].line_nr {
p.fgen_nl()
} else {
p.fgen(' ')
}
}
[if vfmt] [if vfmt]
fn (p mut Parser) fgenln(s string) { fn (p mut Parser) fgenln(s string) {

View File

@ -21,3 +21,4 @@ pub enum Hash {
blake2b_384 blake2b_384
blake2b_512 blake2b_512
} }

View File

@ -1,13 +1,10 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
// Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 // Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256
// hash algorithms as defined in FIPS 180-4. // hash algorithms as defined in FIPS 180-4.
// Based off: https://github.com/golang/go/tree/master/src/crypto/sha512 // Based off: https://github.com/golang/go/tree/master/src/crypto/sha512
// Last commit: https://github.com/golang/go/commit/3ce865d7a0b88714cc433454ae2370a105210c01 // Last commit: https://github.com/golang/go/commit/3ce865d7a0b88714cc433454ae2370a105210c01
module sha512 module sha512
import ( import (
@ -64,7 +61,6 @@ const (
init6_384 = 0xdb0c2e0d64f98fa7 init6_384 = 0xdb0c2e0d64f98fa7
init7_384 = 0x47b5481dbefa4fa4 init7_384 = 0x47b5481dbefa4fa4
) )
// digest represents the partial evaluation of a checksum. // digest represents the partial evaluation of a checksum.
struct Digest { struct Digest {
mut: mut:
@ -118,15 +114,16 @@ fn (d mut Digest) reset() {
d.h[5] = init5 d.h[5] = init5
d.h[6] = init6 d.h[6] = init6
d.h[7] = init7 d.h[7] = init7
} }}
}
d.nx = 0 d.nx = 0
d.len = 0 d.len = 0
} }
// internal // internal
fn new_digest(hash crypto.Hash) &Digest { fn new_digest(hash crypto.Hash) &Digest {
mut d := &Digest{function: hash} mut d := &Digest{
function: hash
}
d.reset() d.reset()
return d return d
} }
@ -164,7 +161,8 @@ fn (d mut Digest) write(p_ []byte) int {
} }
if n >= p.len { if n >= p.len {
p = [] p = []
} else { }
else {
p = p[n..] p = p[n..]
} }
} }
@ -173,7 +171,8 @@ fn (d mut Digest) write(p_ []byte) int {
block(mut d, p[..n]) block(mut d, p[..n])
if n >= p.len { if n >= p.len {
p = [] p = []
} else { }
else {
p = p[n..] p = p[n..]
} }
} }
@ -208,8 +207,7 @@ fn (d &Digest) sum(b_in []byte) []byte {
for b in hash { for b in hash {
b_out << b b_out << b
} }
} }}
}
return b_out return b_out
} }
@ -218,26 +216,21 @@ fn (d mut Digest) checksum() []byte {
mut len := d.len mut len := d.len
mut tmp := [byte(0)].repeat(128) mut tmp := [byte(0)].repeat(128)
tmp[0] = 0x80 tmp[0] = 0x80
if int(len) % 128 < 112 { if int(len) % 128 < 112 {
d.write(tmp[..112 - int(len) % 128]) d.write(tmp[..112 - int(len) % 128])
} else { }
else {
d.write(tmp[..128 + 112 - int(len) % 128]) d.write(tmp[..128 + 112 - int(len) % 128])
} }
// Length in bits. // Length in bits.
len <<= u64(3) len <<= u64(3)
binary.big_endian_put_u64(mut tmp, u64(0)) // upper 64 bits are always zero, because len variable has type u64 binary.big_endian_put_u64(mut tmp, u64(0)) // upper 64 bits are always zero, because len variable has type u64
binary.big_endian_put_u64(mut tmp[8..], len) binary.big_endian_put_u64(mut tmp[8..], len)
d.write(tmp[..16]) d.write(tmp[..16])
if d.nx != 0 { if d.nx != 0 {
panic('d.nx != 0') panic('d.nx != 0')
} }
mut digest := [byte(0)].repeat(size) mut digest := [byte(0)].repeat(size)
binary.big_endian_put_u64(mut digest, d.h[0]) binary.big_endian_put_u64(mut digest, d.h[0])
binary.big_endian_put_u64(mut digest[8..], d.h[1]) binary.big_endian_put_u64(mut digest[8..], d.h[1])
binary.big_endian_put_u64(mut digest[16..], d.h[2]) binary.big_endian_put_u64(mut digest[16..], d.h[2])
@ -248,7 +241,6 @@ fn (d mut Digest) checksum() []byte {
binary.big_endian_put_u64(mut digest[48..], d.h[6]) binary.big_endian_put_u64(mut digest[48..], d.h[6])
binary.big_endian_put_u64(mut digest[56..], d.h[7]) binary.big_endian_put_u64(mut digest[56..], d.h[7])
} }
return digest return digest
} }
@ -297,16 +289,37 @@ fn block(dig mut Digest, p []byte) {
pub fn (d &Digest) size() int { pub fn (d &Digest) size() int {
match d.function { match d.function {
.sha512_224 { return size224 } .sha512_224 {
.sha512_256 { return size256 } return size224
.sha384 { return size384 }
else { return size }
} }
.sha512_256 {
return size256
}
.sha384 {
return size384
}
else {
return size
}}
} }
pub fn (d &Digest) block_size() int { return block_size } pub fn (d &Digest) block_size() int {
return block_size
}
pub fn hexhash(s string) string {
return sum512(s.bytes()).hex()
}
pub fn hexhash_384(s string) string {
return sum384(s.bytes()).hex()
}
pub fn hexhash_512_224(s string) string {
return sum512_224(s.bytes()).hex()
}
pub fn hexhash_512_256(s string) string {
return sum512_256(s.bytes()).hex()
}
pub fn hexhash(s string) string { return sum512(s.bytes()).hex() }
pub fn hexhash_384(s string) string { return sum384(s.bytes()).hex() }
pub fn hexhash_512_224(s string) string { return sum512_224(s.bytes()).hex() }
pub fn hexhash_512_256(s string) string { return sum512_256(s.bytes()).hex() }

View File

@ -1,9 +1,9 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
import crypto.sha512 import crypto.sha512
fn test_crypto_sha512() { fn test_crypto_sha512() {
assert sha512.sum512('This is a sha512 checksum.'.bytes()).hex() == '4143e55fcba7e39b20f62a1368e5eb28f64a8859458886117ac66027832e0f9f5263daec688c439d2d0fa07059334668d39e59543039703dbb7e03ec9da7f8d7' assert sha512.sum512('This is a sha512 checksum.'.bytes()).hex() == '4143e55fcba7e39b20f62a1368e5eb28f64a8859458886117ac66027832e0f9f5263daec688c439d2d0fa07059334668d39e59543039703dbb7e03ec9da7f8d7'
} }

View File

@ -1,19 +1,16 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
// SHA512 block step. // SHA512 block step.
// This is the generic version with no architecture optimizations. // This is the generic version with no architecture optimizations.
// In its own file so that an architecture // In its own file so that an architecture
// optimized verision can be substituted // optimized verision can be substituted
module sha512 module sha512
import math.bits import math.bits
const ( const (
_k = [ _k = [0x428a2f98d728ae22,
0x428a2f98d728ae22,
0x7137449123ef65cd, 0x7137449123ef65cd,
0xb5c0fbcfec4d3b2f, 0xb5c0fbcfec4d3b2f,
0xe9b5dba58189dbbc, 0xe9b5dba58189dbbc,
@ -98,9 +95,7 @@ const(
fn block_generic(dig mut Digest, p_ []byte) { fn block_generic(dig mut Digest, p_ []byte) {
mut p := p_ mut p := p_
mut w := [u64(0)].repeat(80) mut w := [u64(0)].repeat(80)
mut h0 := dig.h[0] mut h0 := dig.h[0]
mut h1 := dig.h[1] mut h1 := dig.h[1]
mut h2 := dig.h[2] mut h2 := dig.h[2]
@ -109,22 +104,18 @@ fn block_generic(dig mut Digest, p_ []byte) {
mut h5 := dig.h[5] mut h5 := dig.h[5]
mut h6 := dig.h[6] mut h6 := dig.h[6]
mut h7 := dig.h[7] mut h7 := dig.h[7]
for p.len >= Chunk { for p.len >= Chunk {
for i := 0; i < 16; i++ { for i := 0; i < 16; i++ {
j := i * 8 j := i * 8
w[i] = u64(u64(u64(p[j])<<56) | u64(u64(p[j+1])<<48) | u64(u64(p[j+2])<<40) | u64(u64(p[j+3])<<32) | w[i] = u64(u64(u64(p[j])<<56) | u64(u64(p[j + 1])<<48) | u64(u64(p[j + 2])<<40) | u64(u64(p[j + 3])<<32) | u64(u64(p[j + 4])<<24) | u64(u64(p[j + 5])<<16) | u64(u64(p[j + 6])<<8) | u64(p[j + 7]))
u64(u64(p[j+4])<<24) | u64(u64(p[j+5])<<16) | u64(u64(p[j+6])<<8) | u64(p[j+7]))
} }
for i := 16; i < 80; i++ { for i := 16; i < 80; i++ {
v1 := w[i - 2] v1 := w[i - 2]
t1 := bits.rotate_left_64(v1, -19) ^ bits.rotate_left_64(v1, -61) ^ (v1>>6) t1 := bits.rotate_left_64(v1, -19) ^ bits.rotate_left_64(v1, -61) ^ (v1>>6)
v2 := w[i - 15] v2 := w[i - 15]
t2 := bits.rotate_left_64(v2, -1) ^ bits.rotate_left_64(v2, -8) ^ (v2>>7) t2 := bits.rotate_left_64(v2, -1) ^ bits.rotate_left_64(v2, -8) ^ (v2>>7)
w[i] = t1 + w[i - 7] + t2 + w[i - 16] w[i] = t1 + w[i - 7] + t2 + w[i - 16]
} }
mut a := h0 mut a := h0
mut b := h1 mut b := h1
mut c := h2 mut c := h2
@ -133,11 +124,9 @@ fn block_generic(dig mut Digest, p_ []byte) {
mut f := h5 mut f := h5
mut g := h6 mut g := h6
mut h := h7 mut h := h7
for i := 0; i < 80; i++ { for i := 0; i < 80; i++ {
t1 := h + (bits.rotate_left_64(e, -14) ^ bits.rotate_left_64(e, -18) ^ bits.rotate_left_64(e, -41)) + ((e & f) ^ (~e & g)) + _k[i] + w[i] t1 := h + (bits.rotate_left_64(e, -14) ^ bits.rotate_left_64(e, -18) ^ bits.rotate_left_64(e, -41)) + ((e & f) ^ (~e & g)) + _k[i] + w[i]
t2 := (bits.rotate_left_64(a, -28) ^ bits.rotate_left_64(a, -34) ^ bits.rotate_left_64(a, -39)) + ((a & b) ^ (a & c) ^ (b & c)) t2 := (bits.rotate_left_64(a, -28) ^ bits.rotate_left_64(a, -34) ^ bits.rotate_left_64(a, -39)) + ((a & b) ^ (a & c) ^ (b & c))
h = g h = g
g = f g = f
f = e f = e
@ -147,7 +136,6 @@ fn block_generic(dig mut Digest, p_ []byte) {
b = a b = a
a = t1 + t2 a = t1 + t2
} }
h0 += a h0 += a
h1 += b h1 += b
h2 += c h2 += c
@ -156,14 +144,13 @@ fn block_generic(dig mut Digest, p_ []byte) {
h5 += f h5 += f
h6 += g h6 += g
h7 += h h7 += h
if Chunk >= p.len { if Chunk >= p.len {
p = [] p = []
} else { }
else {
p = p[Chunk..] p = p[Chunk..]
} }
} }
dig.h[0] = h0 dig.h[0] = h0
dig.h[1] = h1 dig.h[1] = h1
dig.h[2] = h2 dig.h[2] = h2
@ -173,3 +160,4 @@ fn block_generic(dig mut Digest, p_ []byte) {
dig.h[6] = h6 dig.h[6] = h6
dig.h[7] = h7 dig.h[7] = h7
} }

View File

@ -1,10 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module binary module binary
// Little Endian // Little Endian
[inline] [inline]
pub fn little_endian_endian_u16(b []byte) u16 { pub fn little_endian_endian_u16(b []byte) u16 {
@ -37,8 +34,7 @@ pub fn little_endian_put_u32(b mut []byte, v u32) {
[inline] [inline]
pub fn little_endian_u64(b []byte) u64 { pub fn little_endian_u64(b []byte) u64 {
_ = b[7] // bounds check _ = b[7] // bounds check
return u64(b[0]) | u64(u64(b[1])<<u64(8)) | u64(u64(b[2])<<u64(16)) | u64(u64(b[3])<<u64(24)) | return u64(b[0]) | u64(u64(b[1])<<u64(8)) | u64(u64(b[2])<<u64(16)) | u64(u64(b[3])<<u64(24)) | u64(u64(b[4])<<u64(32)) | u64(u64(b[5])<<u64(40)) | u64(u64(b[6])<<u64(48)) | u64(u64(b[7])<<u64(56))
u64(u64(b[4])<<u64(32)) | u64(u64(b[5])<<u64(40)) | u64(u64(b[6])<<u64(48)) | u64(u64(b[7])<<u64(56))
} }
[inline] [inline]
@ -86,8 +82,7 @@ pub fn big_endian_put_u32(b mut []byte, v u32) {
[inline] [inline]
pub fn big_endian_u64(b []byte) u64 { pub fn big_endian_u64(b []byte) u64 {
_ = b[7] // bounds check _ = b[7] // bounds check
return u64(b[7]) | u64(u64(b[6])<<u64(8)) | u64(u64(b[5])<<u64(16)) | u64(u64(b[4])<<u64(24)) | return u64(b[7]) | u64(u64(b[6])<<u64(8)) | u64(u64(b[5])<<u64(16)) | u64(u64(b[4])<<u64(24)) | u64(u64(b[3])<<u64(32)) | u64(u64(b[2])<<u64(40)) | u64(u64(b[1])<<u64(48)) | u64(u64(b[0])<<u64(56))
u64(u64(b[3])<<u64(32)) | u64(u64(b[2])<<u64(40)) | u64(u64(b[1])<<u64(48)) | u64(u64(b[0])<<u64(56))
} }
[inline] [inline]
@ -102,3 +97,4 @@ pub fn big_endian_put_u64(b mut []byte, v u64) {
b[6] = byte(v>>u64(8)) b[6] = byte(v>>u64(8))
b[7] = byte(v) b[7] = byte(v)
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module math module math
const ( const (
@ -15,7 +14,6 @@ const (
sign_mask = (u64(1)<<63) sign_mask = (u64(1)<<63)
frac_mask = ((u64(1)<<u64(shift)) - u64(1)) frac_mask = ((u64(1)<<u64(shift)) - u64(1))
) )
// inf returns positive infinity if sign >= 0, negative infinity if sign < 0. // inf returns positive infinity if sign >= 0, negative infinity if sign < 0.
pub fn inf(sign int) f64 { pub fn inf(sign int) f64 {
v := if sign >= 0 { uvinf } else { uvneginf } v := if sign >= 0 { uvinf } else { uvneginf }
@ -23,7 +21,9 @@ pub fn inf(sign int) f64 {
} }
// nan returns an IEEE 754 ``not-a-number'' value. // nan returns an IEEE 754 ``not-a-number'' value.
pub fn nan() f64 { return f64_from_bits(uvnan) } pub fn nan() f64 {
return f64_from_bits(uvnan)
}
// is_nan reports whether f is an IEEE 754 ``not-a-number'' value. // is_nan reports whether f is an IEEE 754 ``not-a-number'' value.
pub fn is_nan(f f64) bool { pub fn is_nan(f f64) bool {
@ -56,3 +56,4 @@ pub fn is_inf(f f64, sign int) bool {
// } // }
// return x, 0 // return x, 0
// } // }

View File

@ -1,19 +1,16 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module bits module bits
const ( const (
// See http://supertech.csail.mit.edu/papers/debruijn.pdf // See http://supertech.csail.mit.edu/papers/debruijn.pdf
de_bruijn32 = u32(0x077CB531) de_bruijn32 = u32(0x077CB531)
de_bruijn32tab = [ de_bruijn32tab = [byte(0), 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
byte(0), 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
] ]
de_bruijn64 = u64(0x03f79d71b4ca8b09) de_bruijn64 = u64(0x03f79d71b4ca8b09)
de_bruijn64tab = [ de_bruijn64tab = [byte(0), 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
byte(0), 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
@ -27,23 +24,28 @@ const(
m3 = 0x00ff00ff00ff00ff // etc. m3 = 0x00ff00ff00ff00ff // etc.
m4 = 0x0000ffff0000ffff m4 = 0x0000ffff0000ffff
) )
// --- LeadingZeros --- // --- LeadingZeros ---
// leading_zeros8 returns the number of leading zero bits in x; the result is 8 for x == 0. // leading_zeros8 returns the number of leading zero bits in x; the result is 8 for x == 0.
pub fn leading_zeros8(x byte) int { return 8 - len8(x) } pub fn leading_zeros8(x byte) int {
return 8 - len8(x)
}
// leading_zeros16 returns the number of leading zero bits in x; the result is 16 for x == 0. // leading_zeros16 returns the number of leading zero bits in x; the result is 16 for x == 0.
pub fn leading_zeros16(x u16) int { return 16 - len16(x) } pub fn leading_zeros16(x u16) int {
return 16 - len16(x)
}
// leading_zeros32 returns the number of leading zero bits in x; the result is 32 for x == 0. // leading_zeros32 returns the number of leading zero bits in x; the result is 32 for x == 0.
pub fn leading_zeros32(x u32) int { return 32 - len32(x) } pub fn leading_zeros32(x u32) int {
return 32 - len32(x)
}
// leading_zeros64 returns the number of leading zero bits in x; the result is 64 for x == 0. // leading_zeros64 returns the number of leading zero bits in x; the result is 64 for x == 0.
pub fn leading_zeros64(x u64) int { return 64 - len64(x) } pub fn leading_zeros64(x u64) int {
return 64 - len64(x)
}
// --- TrailingZeros --- // --- TrailingZeros ---
// trailing_zeros8 returns the number of trailing zero bits in x; the result is 8 for x == 0. // trailing_zeros8 returns the number of trailing zero bits in x; the result is 8 for x == 0.
pub fn trailing_zeros8(x byte) int { pub fn trailing_zeros8(x byte) int {
return int(ntz8_tab[x]) return int(ntz8_tab[x])
@ -87,7 +89,6 @@ pub fn trailing_zeros64(x u64) int {
} }
// --- OnesCount --- // --- OnesCount ---
// ones_count8 returns the number of one bits ("population count") in x. // ones_count8 returns the number of one bits ("population count") in x.
pub fn ones_count8(x byte) int { pub fn ones_count8(x byte) int {
return int(pop8_tab[x]) return int(pop8_tab[x])
@ -135,7 +136,6 @@ pub fn ones_count64(x u64) int {
} }
// --- RotateLeft --- // --- RotateLeft ---
// rotate_left_8 returns the value of x rotated left by (k mod 8) bits. // rotate_left_8 returns the value of x rotated left by (k mod 8) bits.
// To rotate x right by k bits, call rotate_left_8(x, -k). // To rotate x right by k bits, call rotate_left_8(x, -k).
// //
@ -181,7 +181,6 @@ pub fn rotate_left_64(x u64, k int) u64 {
} }
// --- Reverse --- // --- Reverse ---
// reverse8 returns the value of x with its bits in reversed order. // reverse8 returns the value of x with its bits in reversed order.
[inline] [inline]
pub fn reverse8(x byte) byte { pub fn reverse8(x byte) byte {
@ -215,7 +214,6 @@ pub fn reverse64(x u64) u64 {
} }
// --- ReverseBytes --- // --- ReverseBytes ---
// reverse_bytes16 returns the value of x with its bytes in reversed order. // reverse_bytes16 returns the value of x with its bytes in reversed order.
// //
// This function's execution time does not depend on the inputs. // This function's execution time does not depend on the inputs.
@ -246,7 +244,6 @@ pub fn reverse_bytes64(x u64) u64 {
} }
// --- Len --- // --- Len ---
// len8 returns the minimum number of bits required to represent x; the result is 0 for x == 0. // len8 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
pub fn len8(x byte) int { pub fn len8(x byte) int {
return int(len8_tab[x]) return int(len8_tab[x])
@ -296,3 +293,4 @@ pub fn len64(x u64) int {
} }
return n + int(len8_tab[y]) return n + int(len8_tab[y])
} }

View File

@ -1,12 +1,10 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module bits module bits
const ( const (
ntz8_tab = [ ntz8_tab = [byte(0x08), 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
byte(0x08), 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
@ -23,8 +21,7 @@ const(
0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
] ]
pop8_tab = [ pop8_tab = [byte(0x00), 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
byte(0x00), 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
@ -41,8 +38,7 @@ const(
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08,
] ]
rev8_tab = [ rev8_tab = [byte(0x00), 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
byte(0x00), 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
@ -59,8 +55,7 @@ const(
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
] ]
len8_tab = [ len8_tab = [byte(0x00), 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
byte(0x00), 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
@ -78,3 +73,4 @@ const(
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
] ]
) )

View File

@ -1,7 +1,6 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module math module math
pub const ( pub const (
@ -9,30 +8,25 @@ pub const (
pi = 3.14159265358979323846264338327950288419716939937510582097494459 pi = 3.14159265358979323846264338327950288419716939937510582097494459
phi = 1.61803398874989484820458683436563811772030917980576286213544862 phi = 1.61803398874989484820458683436563811772030917980576286213544862
tau = 6.28318530717958647692528676655900576839433879875021164194988918 tau = 6.28318530717958647692528676655900576839433879875021164194988918
sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974 sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974
sqrt_e = 1.64872127070012814684865078781416357165377610071014801157507931 sqrt_e = 1.64872127070012814684865078781416357165377610071014801157507931
sqrt_pi = 1.77245385090551602729816748334114518279754945612238712821380779 sqrt_pi = 1.77245385090551602729816748334114518279754945612238712821380779
sqrt_tau = 2.50662827463100050241576528481104525300698674060993831662992357 sqrt_tau = 2.50662827463100050241576528481104525300698674060993831662992357
sqrt_phi = 1.27201964951406896425242246173749149171560804184009624861664038 sqrt_phi = 1.27201964951406896425242246173749149171560804184009624861664038
ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 ln2 = 0.693147180559945309417232121458176568075500134360255254120680009
log2_e = 1.0 / ln2 log2_e = 1.0 / ln2
ln10 = 2.30258509299404568401799145468436420760110148862877297603332790 ln10 = 2.30258509299404568401799145468436420760110148862877297603332790
log10_e = 1.0 / ln10 log10_e = 1.0 / ln10
) )
// Floating-point limit values // Floating-point limit values
// max is the largest finite value representable by the type. // max is the largest finite value representable by the type.
// smallest_non_zero is the smallest positive, non-zero value representable by the type. // smallest_non_zero is the smallest positive, non-zero value representable by the type.
pub const ( pub const (
max_f32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23 max_f32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23
smallest_non_zero_f32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23) smallest_non_zero_f32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)
max_f64 = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52 max_f64 = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52
smallest_non_zero_f64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52) smallest_non_zero_f64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52)
) )
// Integer limit values // Integer limit values
pub const ( pub const (
max_i8 = 127 max_i8 = 127
@ -51,3 +45,4 @@ pub const (
max_u32 = 4294967295 max_u32 = 4294967295
max_u64 = 18446744073709551615 max_u64 = 18446744073709551615
) )

View File

@ -1,8 +1,7 @@
module math module math
const ( const (
factorials = [ factorials = [f64(1.000000000000000000000e+0),/* 0! */
f64(1.000000000000000000000e+0), /* 0! */
1.000000000000000000000e+0,/* 1! */ 1.000000000000000000000e+0,/* 1! */
2.000000000000000000000e+0,/* 2! */ 2.000000000000000000000e+0,/* 2! */
6.000000000000000000000e+0,/* 3! */ 6.000000000000000000000e+0,/* 3! */
@ -175,3 +174,4 @@ const(
7.257415615307998967397e+306/* 170! */ 7.257415615307998967397e+306/* 170! */
] ]
) )

View File

@ -1,46 +1,97 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module math module math
#include <math.h> #include <math.h>
fn C.acos(x f64) f64 fn C.acos(x f64) f64
fn C.asin(x f64) f64 fn C.asin(x f64) f64
fn C.atan(x f64) f64 fn C.atan(x f64) f64
fn C.atan2(y f64, x f64) f64 fn C.atan2(y f64, x f64) f64
fn C.cbrt(x f64) f64 fn C.cbrt(x f64) f64
fn C.ceil(x f64) f64 fn C.ceil(x f64) f64
fn C.cos(x f64) f64 fn C.cos(x f64) f64
fn C.cosh(x f64) f64 fn C.cosh(x f64) f64
fn C.erf(x f64) f64 fn C.erf(x f64) f64
fn C.erfc(x f64) f64 fn C.erfc(x f64) f64
fn C.exp(x f64) f64 fn C.exp(x f64) f64
fn C.exp2(x f64) f64 fn C.exp2(x f64) f64
fn C.fabs(x f64) f64 fn C.fabs(x f64) f64
fn C.floor(x f64) f64 fn C.floor(x f64) f64
fn C.fmod(x f64, y f64) f64 fn C.fmod(x f64, y f64) f64
fn C.hypot(x f64, y f64) f64 fn C.hypot(x f64, y f64) f64
fn C.log(x f64) f64 fn C.log(x f64) f64
fn C.log2(x f64) f64 fn C.log2(x f64) f64
fn C.log10(x f64) f64 fn C.log10(x f64) f64
fn C.lgamma(x f64) f64 fn C.lgamma(x f64) f64
fn C.pow(x f64, y f64) f64 fn C.pow(x f64, y f64) f64
fn C.round(x f64) f64 fn C.round(x f64) f64
fn C.sin(x f64) f64 fn C.sin(x f64) f64
fn C.sinh(x f64) f64 fn C.sinh(x f64) f64
fn C.sqrt(x f64) f64 fn C.sqrt(x f64) f64
fn C.tgamma(x f64) f64 fn C.tgamma(x f64) f64
fn C.tan(x f64) f64 fn C.tan(x f64) f64
fn C.tanh(x f64) f64 fn C.tanh(x f64) f64
fn C.trunc(x f64) f64 fn C.trunc(x f64) f64
// NOTE // NOTE
// When adding a new function, please make sure it's in the right place. // When adding a new function, please make sure it's in the right place.
// All functions are sorted alphabetically. // All functions are sorted alphabetically.
// Returns the absolute value. // Returns the absolute value.
pub fn abs(a f64) f64 { pub fn abs(a f64) f64 {
return C.fabs(a) return C.fabs(a)
@ -133,16 +184,13 @@ pub fn exp2(a f64) f64 {
// factorial calculates the factorial of the provided value. // factorial calculates the factorial of the provided value.
pub fn factorial(n f64) f64 { pub fn factorial(n f64) f64 {
// For a large postive argument (n >= factorials.len) return max_f64 // For a large postive argument (n >= factorials.len) return max_f64
if n >= factorials.len { if n >= factorials.len {
return max_f64 return max_f64
} }
// Otherwise return n!. // Otherwise return n!.
if n == f64(i64(n)) && n >= 0.0 { if n == f64(i64(n)) && n >= 0.0 {
return factorials[i64(n)] return factorials[i64(n)]
} }
return gamma(n + 1.0) return gamma(n + 1.0)
} }
@ -268,6 +316,7 @@ pub fn sinh(a f64) f64 {
pub fn sqrt(a f64) f64 { pub fn sqrt(a f64) f64 {
return C.sqrt(a) return C.sqrt(a)
} }
// tan calculates tangent. // tan calculates tangent.
pub fn tan(a f64) f64 { pub fn tan(a f64) f64 {
return C.tan(a) return C.tan(a)
@ -283,3 +332,4 @@ pub fn tanh(a f64) f64 {
pub fn trunc(a f64) f64 { pub fn trunc(a f64) f64 {
return C.trunc(a) return C.trunc(a)
} }

View File

@ -1,9 +1,7 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module math module math
// f32_bits returns the IEEE 754 binary representation of f, // f32_bits returns the IEEE 754 binary representation of f,
// with the sign bit of f and the result in the same bit position. // with the sign bit of f and the result in the same bit position.
// f32_bits(f32_from_bits(x)) == x. // f32_bits(f32_from_bits(x)) == x.
@ -37,3 +35,4 @@ pub fn f64_from_bits(b u64) f64 {
p := *f64(&b) p := *f64(&b)
return *p return *p
} }