In file main.go is my implementation of FixedToFloat64 vs wl_fixed_to_double, the comments can help you to understand my codes. Since event wl_touch::orientation's orientation arg is fixed value and can be negative, I think this bug is not acceptable. Besides, I don't understand how wl_fixed_to_double works, can anyone illustrate that for me?
--------------------------------程安絮
package main /* double wl_fixed_to_double (unsigned int fix){ union di { double d; long i; }; union di u; u.i = ((1023L + 44L) << 52) + (1L << 51) + fix; return u.d - (3L << 43); } */ import "C" import ( . "fmt" "unsafe" ) func main() { var i uint64 var n byte for i = 0; i < 0x100000000; i++ { fMy := MyFixedToFloat64(uint32(i)) fWl := float64( C.wl_fixed_to_double( C.uint(i) ) ) if fMy != fWl { Printf("i: %X\nfMy: %x\nfWl: %x\n", i, fMy, fWl) n++ if n==5{break} } } } //main func MyFixedToFloat64(fix uint32) float64 { // fixed value have 1 sign bit and 31 value bits // decimal point between bit9 and bit8(right to left index order, start at 1) // get sign bit var sign uint64 = uint64( fix&0x80000000 )<<32 // shift out 1 sign bit, pad 1 value bit of `0` on right side, value bits increase to 32 // decimal point and value bits move together(1bit left), don't change the value; // decimal point between bit10 and bit9 fixValue:=fix<<1 // if value is zero // then return float64 value should be `+0` or `-0`, depends on the sign bit if fixValue == 0 { // wayland use "Native Byteorder", so no need to worry about byte-endian // just use pointer convertion to convert bits to float64 value return *(*float64)(unsafe.Pointer(&sign) ) } // shift out all successive `0`s on the left side and save number of zeros shifted out in `n0` // the most left `1` will be the hidden bit of Fraction, should be shifted out too // shift out n0 bits of `0` and 1 bit of `1` on left, pad in n0+1 bits of `0` on the right, so number of value bits is still 32 // decimal point and value bits move together(n0+1bits left), don't change the value; // decimal point between bit(n0+1+10) and bit(n0+1+9) i.e bit(n0+11) and bit(n0+10) var n0 uint64 for { if fixValue&0x80000000 != 0 { fixValue <<=1 break } fixValue <<= 1 n0++ } //for // float64 have 52 Fraction bits, fixValue only have 32 bits // so fixValue should be convert to uint64 and shift left 20 bits(pad 20bits of `0` on the right side) // decimal point and value bits move together(20bits left), don't change the value; // decimal point between bit(20+n0+11) and bit(20+n0+10) i.e bit(31+n0) and bit(30+n0) var frac uint64 = uint64(fixValue) << 20 // float64's decimal point between bit53 and bit 52 // so float64's decimal point should move 52-(30+n0)bits right i.e (22-n0)bits right // move decimal point right equals to increase exponent, so exponent should increase by 22-n0 // float64's exponent Biased up by 1023, so exponent should be 1023+22-n0 i.e 1045-n0 // shift left 52bits put exponent at the correct place var exp uint64 = (1045 - n0) << 52 // `or` sign, exponent and fraction together, get the float64bits fBits := sign | exp | frac // pointer convert float64bits to float64 value return *(*float64)(unsafe.Pointer(&fBits)) } // func