Some Go 1.12 and Go 1.13 bugs are preventing CBOR encoder from encoding sNaN values without them becoming qNaN values. This is a blocker for #91.
Works: Casting float32 to float64 directly doesn't turn sNaN into qNaN, which is good.
Go bug 1: Casting a float64 to float32 turns sNaN into qNaN.
Go bug 2: func (Value) Float in Go's reflect package turns float32 sNaN into float64 qNaN.
I wrote code to convert NaN while preserving signalling at cbor-go/float16 in FromNaN32ps. Its for float32 to float16 (IEEE 754 binary16) but the same principal applies.
Here are the reproducers for bug 1 and 2.
Bug 1: https://play.golang.org/p/kzLI9A07wRv
Go/Golang lost bit when casting float64 to float32, forced sNaN to qNaN
u32=0x7f800001, u32bis=0x7fc00001, diff=0x00400000
package main
import (
"fmt"
"math"
)
func main() {
// init float32 with sNaN
const u32 = uint32(0x7f800001) // IEEE 754 binary32 representation of sNaN
f32 := math.Float32frombits(u32)
// cast float32 to float64
f64 := float64(f32)
u64 := math.Float64bits(f64)
// test passes
sbit64 := uint64(0x8000000000000) // the signalling/quiet bit for IEEE 754 binary64
if (u64 & sbit64) != 0 {
fmt.Printf("Go/Golang lost bit when casting float32 to float64, forced sNaN to qNaN\n")
}
f32bis := float32(f64)
u32bis := math.Float32bits(f32bis)
diff := u32bis ^ u32
// test fails
if diff != 0 {
fmt.Printf("Go/Golang lost bit when casting float64 to float32, forced sNaN to qNaN\n")
fmt.Printf("u32=0x%08x, u32bis=0x%08x, diff=0x%08x\n", u32, u32bis, diff)
}
}
Bug 2: https://play.golang.org/p/T7orv6p_C6h
Want sNaN, got qNaN
package main
import (
"fmt"
"math"
"reflect"
)
func main() {
// Create a float32 signalling Nan.
f32 := math.Float32frombits(0x7f800001)
// Create a reflect.Value object from f32.
v := reflect.ValueOf(f32)
// Get its underlying floating-point value as float64.
f64 := v.Float()
// Returned float64 value has quiet-bit on.
u64 := math.Float64bits(f64)
if (u64 & 0x8000000000000) != 0 {
fmt.Println("Want sNaN, got qNaN")
}
}
Some Go 1.12 and Go 1.13 bugs are preventing CBOR encoder from encoding sNaN values without them becoming qNaN values. This is a blocker for #91.
Works: Casting float32 to float64 directly doesn't turn sNaN into qNaN, which is good.
Go bug 1: Casting a float64 to float32 turns sNaN into qNaN.
Go bug 2:
func (Value) Floatin Go'sreflectpackage turns float32 sNaN into float64 qNaN.I wrote code to convert NaN while preserving signalling at cbor-go/float16 in
FromNaN32ps. Its for float32 to float16 (IEEE 754 binary16) but the same principal applies.Here are the reproducers for bug 1 and 2.
Bug 1: https://play.golang.org/p/kzLI9A07wRv
Bug 2: https://play.golang.org/p/T7orv6p_C6h