Source File
moremath.go
Belonging Package
github.com/tetratelabs/wazero/internal/moremath
package moremathimport ()// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/values.html#floating-pointconst (// F32CanonicalNaNBits is the 32-bit float where payload's MSB equals 1 and others are all zero.F32CanonicalNaNBits = uint32(0x7fc0_0000)// F32CanonicalNaNBitsMask can be used to judge the value `v` is canonical nan as "v&F32CanonicalNaNBitsMask == F32CanonicalNaNBits"F32CanonicalNaNBitsMask = uint32(0x7fff_ffff)// F64CanonicalNaNBits is the 64-bit float where payload's MSB equals 1 and others are all zero.F64CanonicalNaNBits = uint64(0x7ff8_0000_0000_0000)// F64CanonicalNaNBitsMask can be used to judge the value `v` is canonical nan as "v&F64CanonicalNaNBitsMask == F64CanonicalNaNBits"F64CanonicalNaNBitsMask = uint64(0x7fff_ffff_ffff_ffff)// F32ArithmeticNaNPayloadMSB is used to extract the most significant bit of payload of 32-bit arithmetic NaN valuesF32ArithmeticNaNPayloadMSB = uint32(0x0040_0000)// F32ExponentMask is used to extract the exponent of 32-bit floating point.F32ExponentMask = uint32(0x7f80_0000)// F32ArithmeticNaNBits is an example 32-bit arithmetic NaN.F32ArithmeticNaNBits = F32CanonicalNaNBits | 0b1 // Set first bit to make this different from the canonical NaN.// F64ArithmeticNaNPayloadMSB is used to extract the most significant bit of payload of 64-bit arithmetic NaN valuesF64ArithmeticNaNPayloadMSB = uint64(0x0008_0000_0000_0000)// F64ExponentMask is used to extract the exponent of 64-bit floating point.F64ExponentMask = uint64(0x7ff0_0000_0000_0000)// F64ArithmeticNaNBits is an example 64-bit arithmetic NaN.F64ArithmeticNaNBits = F64CanonicalNaNBits | 0b1 // Set first bit to make this different from the canonical NaN.)// WasmCompatMin64 is the Wasm spec compatible variant of math.Min for 64-bit floating points.func (, float64) float64 {switch {case math.IsNaN() || math.IsNaN():return returnF64NaNBinOp(, )case math.IsInf(, -1) || math.IsInf(, -1):return math.Inf(-1)case == 0 && == :if math.Signbit() {return}return}if < {return}return}// WasmCompatMin32 is the Wasm spec compatible variant of math.Min for 32-bit floating points.func (, float32) float32 {, := float64(), float64()switch {case math.IsNaN() || math.IsNaN():return returnF32NaNBinOp(, )case math.IsInf(, -1) || math.IsInf(, -1):return float32(math.Inf(-1))case == 0 && == :if math.Signbit() {return}return}if < {return}return}// WasmCompatMax64 is the Wasm spec compatible variant of math.Max for 64-bit floating points.func (, float64) float64 {switch {case math.IsNaN() || math.IsNaN():return returnF64NaNBinOp(, )case math.IsInf(, 1) || math.IsInf(, 1):return math.Inf(1)case == 0 && == :if math.Signbit() {return}return}if > {return}return}// WasmCompatMax32 is the Wasm spec compatible variant of math.Max for 32-bit floating points.func (, float32) float32 {, := float64(), float64()switch {case math.IsNaN() || math.IsNaN():return returnF32NaNBinOp(, )case math.IsInf(, 1) || math.IsInf(, 1):return float32(math.Inf(1))case == 0 && == :if math.Signbit() {return}return}if > {return}return}// WasmCompatNearestF32 is the Wasm spec compatible variant of math.Round, used for Nearest instruction.// For example, this converts 1.9 to 2.0, and this has the semantics of LLVM's rint intrinsic.//// e.g. math.Round(-4.5) results in -5 while this results in -4.//// See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic.func ( float32) float32 {var float32// TODO: look at https://github.com/bytecodealliance/wasmtime/pull/2171 and reconsider this algorithmif != 0 {:= float32(math.Ceil(float64())):= float32(math.Floor(float64())):= math.Abs(float64( - )):= math.Abs(float64( - )):= / 2.0if < {=} else if == && float32(math.Floor(float64())) == {=} else {=}} else {=}return returnF32UniOp(, )}// WasmCompatNearestF64 is the Wasm spec compatible variant of math.Round, used for Nearest instruction.// For example, this converts 1.9 to 2.0, and this has the semantics of LLVM's rint intrinsic.//// e.g. math.Round(-4.5) results in -5 while this results in -4.//// See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic.func ( float64) float64 {// TODO: look at https://github.com/bytecodealliance/wasmtime/pull/2171 and reconsider this algorithmvar float64if != 0 {:= math.Ceil():= math.Floor():= math.Abs( - ):= math.Abs( - ):= / 2.0if < {=} else if == && math.Floor() == {=} else {=}} else {=}return returnF64UniOp(, )}// WasmCompatCeilF32 is the same as math.Ceil on 32-bit except that// the returned NaN value follows the Wasm specification on NaN// propagation.// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc ( float32) float32 {return returnF32UniOp(, float32(math.Ceil(float64())))}// WasmCompatCeilF64 is the same as math.Ceil on 64-bit except that// the returned NaN value follows the Wasm specification on NaN// propagation.// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc ( float64) float64 {return returnF64UniOp(, math.Ceil())}// WasmCompatFloorF32 is the same as math.Floor on 32-bit except that// the returned NaN value follows the Wasm specification on NaN// propagation.// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc ( float32) float32 {return returnF32UniOp(, float32(math.Floor(float64())))}// WasmCompatFloorF64 is the same as math.Floor on 64-bit except that// the returned NaN value follows the Wasm specification on NaN// propagation.// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc ( float64) float64 {return returnF64UniOp(, math.Floor())}// WasmCompatTruncF32 is the same as math.Trunc on 32-bit except that// the returned NaN value follows the Wasm specification on NaN// propagation.// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc ( float32) float32 {return returnF32UniOp(, float32(math.Trunc(float64())))}// WasmCompatTruncF64 is the same as math.Trunc on 64-bit except that// the returned NaN value follows the Wasm specification on NaN// propagation.// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc ( float64) float64 {return returnF64UniOp(, math.Trunc())}func f32IsNaN( float32) bool {return != // this is how NaN is defined.}func f64IsNaN( float64) bool {return != // this is how NaN is defined.}// returnF32UniOp returns the result of 32-bit unary operation. This accepts `original` which is the operand,// and `result` which is its result. This returns the `result` as-is if the result is not NaN. Otherwise, this follows// the same logic as in the reference interpreter as well as the amd64 and arm64 floating point handling.func returnF32UniOp(, float32) float32 {// Following the same logic as in the reference interpreter:// https://github.com/WebAssembly/spec/blob/d48af683f5e6d00c13f775ab07d29a15daf92203/interpreter/exec/fxx.ml#L115-L122if !f32IsNaN() {return}if !f32IsNaN() {return math.Float32frombits(F32CanonicalNaNBits)}return math.Float32frombits(math.Float32bits() | F32CanonicalNaNBits)}// returnF32UniOp returns the result of 64-bit unary operation. This accepts `original` which is the operand,// and `result` which is its result. This returns the `result` as-is if the result is not NaN. Otherwise, this follows// the same logic as in the reference interpreter as well as the amd64 and arm64 floating point handling.func returnF64UniOp(, float64) float64 {// Following the same logic as in the reference interpreter (== amd64 and arm64's behavior):// https://github.com/WebAssembly/spec/blob/d48af683f5e6d00c13f775ab07d29a15daf92203/interpreter/exec/fxx.ml#L115-L122if !f64IsNaN() {return}if !f64IsNaN() {return math.Float64frombits(F64CanonicalNaNBits)}return math.Float64frombits(math.Float64bits() | F64CanonicalNaNBits)}// returnF64NaNBinOp returns a NaN for 64-bit binary operations. `x` and `y` are original floats// and at least one of them is NaN. The returned NaN is guaranteed to comply with the NaN propagation// procedure: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc returnF64NaNBinOp(, float64) float64 {if f64IsNaN() {return math.Float64frombits(math.Float64bits() | F64CanonicalNaNBits)} else {return math.Float64frombits(math.Float64bits() | F64CanonicalNaNBits)}}// returnF64NaNBinOp returns a NaN for 32-bit binary operations. `x` and `y` are original floats// and at least one of them is NaN. The returned NaN is guaranteed to comply with the NaN propagation// procedure: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/numerics.html#nan-propagationfunc returnF32NaNBinOp(, float32) float32 {if f32IsNaN() {return math.Float32frombits(math.Float32bits() | F32CanonicalNaNBits)} else {return math.Float32frombits(math.Float32bits() | F32CanonicalNaNBits)}}
![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |