github.com/Kintar/etxt@v0.0.0-20221224033739-2fc69f000137/efixed/fixed_point_test.go (about) 1 //go:build gtxt 2 3 package efixed 4 5 import "testing" 6 import "math/rand" 7 import "time" 8 import "math" 9 10 import "golang.org/x/image/math/fixed" 11 12 func TestFromFloat(t *testing.T) { 13 tests := []struct { 14 in float64 15 low fixed.Int26_6 16 high fixed.Int26_6 17 }{ 18 {in: 0.0, low: 0, high: 0}, 19 {in: 1.0, low: 64, high: 64}, 20 {in: -1.0, low: -64, high: -64}, 21 {in: 0.5, low: 32, high: 32}, 22 {in: 3.14, low: 201, high: 201}, 23 {in: -3.14, low: -201, high: -201}, 24 {in: 8.33, low: 533, high: 533}, 25 {in: 8.3359375, low: 533, high: 534}, 26 {in: 8.3359374, low: 533, high: 533}, 27 {in: 8.3359376, low: 534, high: 534}, 28 {in: -8.3359375, low: -534, high: -533}, 29 {in: -8.3359374, low: -533, high: -533}, 30 {in: -8.3359376, low: -534, high: -534}, 31 {in: 33554432, low: 2147483647, high: 2147483647}, 32 {in: -33554432, low: -2147483648, high: -2147483648}, 33 {in: -33554432.015625, low: -2147483648, high: -2147483648}, 34 } 35 36 for i, test := range tests { 37 low, high := FromFloat64(test.in) 38 if low != test.low || high != test.high { 39 str := "test #%d: in (%.6f) expected outs %d (%.6f) and %d (%.6f), but got %d (%.6f) and %d (%.6f)" 40 t.Fatalf(str, i, test.in, test.low, ToFloat64(test.low), test.high, ToFloat64(test.high), low, ToFloat64(low), high, ToFloat64(high)) 41 } 42 } 43 44 // test expected panics 45 for _, value := range []float64{math.NaN(), math.Inf(1), math.Inf(-1), -33554432.015626, 33554432.0000001} { 46 func() { 47 defer func() { _ = recover() }() 48 FromFloat64(value) 49 t.Fatalf("expected %f to panic", value) 50 }() 51 } 52 } 53 54 func TestHalfRounding(t *testing.T) { 55 halfUpTests := []struct { 56 in fixed.Int26_6 57 out fixed.Int26_6 58 }{ 59 {in: 0, out: 0}, {in: 32, out: 64}, {in: 31, out: 0}, 60 {in: -32, out: 0}, {in: -31, out: 0}, {in: -33, out: -64}, 61 {in: FromFloat64RoundToZero(3.1416), out: FromFloat64RoundToZero(3.00)}, 62 {in: FromFloat64RoundToZero(-3.1416), out: FromFloat64RoundToZero(-3.00)}, 63 {in: FromFloat64RoundToZero(-3.9), out: FromFloat64RoundToZero(-4.00)}, 64 {in: FromFloat64RoundToZero(3.9), out: FromFloat64RoundToZero(4.00)}, 65 {in: FromFloat64RoundToZero(112.4), out: FromFloat64RoundToZero(112.00)}, 66 {in: FromFloat64RoundToZero(112.5), out: FromFloat64RoundToZero(113.00)}, 67 {in: FromFloat64RoundToZero(112.6), out: FromFloat64RoundToZero(113.00)}, 68 {in: FromFloat64RoundToZero(-112.4), out: FromFloat64RoundToZero(-112.00)}, 69 {in: FromFloat64RoundToZero(-112.5), out: FromFloat64RoundToZero(-112.00)}, 70 {in: FromFloat64RoundToZero(-112.6), out: FromFloat64RoundToZero(-113.00)}, 71 } 72 73 // round half up tests 74 for i, test := range halfUpTests { 75 got := RoundHalfUp(test.in) 76 if got != test.out { 77 str := "test #%d: in %d (%.6f) expected out %d (%.6f) but got %d (%.6f)" 78 t.Fatalf(str, i, test.in, ToFloat64(test.in), test.out, ToFloat64(test.out), got, ToFloat64(got)) 79 } 80 } 81 82 // round half down tests (half up tests but with flipped sign) 83 for i, test := range halfUpTests { 84 got := RoundHalfDown(-test.in) 85 if got != -test.out { 86 str := "test #%d: in %d (%.6f) expected out %d (%.6f) but got %d (%.6f)" 87 t.Fatalf(str, i, -test.in, ToFloat64(-test.in), -test.out, ToFloat64(-test.out), got, ToFloat64(got)) 88 } 89 } 90 91 // consistency test between round half up and round half down 92 rand.Seed(time.Now().UnixNano()) 93 for i := 0; i < 100; i++ { 94 value := fixed.Int26_6(rand.Int31n(1<<26) - (1 << 25)) 95 up := RoundHalfUp(-value) 96 down := RoundHalfDown(value) 97 if up != -down { 98 str := "rand test: in %d (%.6f) caused discordant output, up with -in returned %d (%.6f), and down returned %d (%.6f)" 99 t.Fatalf(str, i, value, ToFloat64(value), up, ToFloat64(up), down, ToFloat64(down)) 100 } 101 } 102 } 103 104 func TestIntHalf(t *testing.T) { 105 halfUpTests := []struct { 106 in fixed.Int26_6 107 out int 108 }{ 109 {in: 0, out: 0}, {in: 32, out: 1}, {in: 31, out: 0}, 110 {in: -32, out: 0}, {in: -31, out: 0}, {in: -33, out: -1}, 111 {in: FromFloat64RoundToZero(3.1416), out: 3}, 112 {in: FromFloat64RoundToZero(-3.1416), out: -3}, 113 {in: FromFloat64RoundToZero(-3.9), out: -4}, 114 {in: FromFloat64RoundToZero(3.9), out: 4}, 115 {in: FromFloat64RoundToZero(112.4), out: 112}, 116 {in: FromFloat64RoundToZero(112.5), out: 113}, 117 {in: FromFloat64RoundToZero(112.6), out: 113}, 118 {in: FromFloat64RoundToZero(-112.4), out: -112}, 119 {in: FromFloat64RoundToZero(-112.5), out: -112}, 120 {in: FromFloat64RoundToZero(-112.6), out: -113}, 121 } 122 123 // round half up tests 124 for i, test := range halfUpTests { 125 got := ToIntHalfUp(test.in) 126 if got != test.out { 127 str := "test #%d: in %d (%.6f) expected out %d but got %d" 128 t.Fatalf(str, i, test.in, ToFloat64(test.in), test.out, got) 129 } 130 } 131 132 // round half down tests (half up tests but with flipped sign) 133 for i, test := range halfUpTests { 134 got := ToIntHalfDown(-test.in) 135 if got != -test.out { 136 str := "test #%d: in %d (%.6f) expected out %d but got %d" 137 t.Fatalf(str, i, test.in, ToFloat64(test.in), test.out, got) 138 } 139 } 140 141 // consistency test between int half up and int half down 142 rand.Seed(time.Now().UnixNano()) 143 for i := 0; i < 100; i++ { 144 value := fixed.Int26_6(rand.Int31n(1<<26) - (1 << 25)) 145 up := ToIntHalfUp(value) 146 down := ToIntHalfDown(-value) 147 if -up != down { 148 str := "rand test: in %d (%.6f) caused discordant output, up with in returned %d, and down with -in returned %d" 149 t.Fatalf(str, i, value, ToFloat64(value), up, down) 150 } 151 } 152 } 153 154 func TestQuantizeFract(t *testing.T) { 155 upTests := []struct { 156 step uint8 157 in fixed.Int26_6 158 out fixed.Int26_6 159 }{ 160 {step: 1, in: 26, out: 26}, {step: 1, in: 27, out: 27}, {step: 1, in: 45, out: 45}, 161 {step: 2, in: 26, out: 26}, {step: 2, in: 27, out: 28}, {step: 2, in: 45, out: 46}, 162 {step: 3, in: 26, out: 27}, {step: 3, in: 27, out: 27}, {step: 3, in: 45, out: 45}, 163 {step: 4, in: 26, out: 28}, {step: 4, in: 27, out: 28}, {step: 4, in: 45, out: 44}, 164 {step: 5, in: 62, out: 60}, {step: 5, in: 63, out: 64}, {step: 5, in: 59, out: 60}, 165 {step: 5, in: 67, out: 69}, {step: 5, in: 66, out: 64}, 166 167 {step: 1, in: -26, out: -26}, {step: 1, in: -27, out: -27}, {step: 1, in: -45, out: -45}, 168 {step: 2, in: -26, out: -26}, {step: 2, in: -27, out: -26}, {step: 2, in: -45, out: -44}, 169 {step: 3, in: -26, out: -27}, {step: 3, in: -27, out: -27}, {step: 3, in: -45, out: -45}, 170 {step: 4, in: -26, out: -24}, {step: 4, in: -27, out: -28}, {step: 4, in: -45, out: -44}, 171 {step: 5, in: -62, out: -60}, {step: 5, in: -63, out: -64}, {step: 5, in: -59, out: -60}, 172 {step: 5, in: -67, out: -69}, {step: 5, in: -66, out: -64}, 173 } 174 175 for i, test := range upTests { 176 got := QuantizeFractUp(test.in, test.step) 177 if got != test.out { 178 str := "test #%d: with step %d, input %.6f (%d) expected out %.6f (%d) but got %.6f (%d" 179 t.Fatalf(str, i, test.step, ToFloat64(test.in), test.in, ToFloat64(test.out), test.out, ToFloat64(got), got) 180 } 181 } 182 183 // ---- down tests ---- 184 185 downTests := []struct { 186 step uint8 187 in fixed.Int26_6 188 out fixed.Int26_6 189 }{ 190 {step: 1, in: 26, out: 26}, {step: 1, in: 27, out: 27}, {step: 1, in: 45, out: 45}, 191 {step: 2, in: 26, out: 26}, {step: 2, in: 27, out: 26}, {step: 2, in: 45, out: 44}, 192 {step: 3, in: 26, out: 27}, {step: 3, in: 27, out: 27}, {step: 3, in: 45, out: 45}, 193 {step: 4, in: 26, out: 24}, {step: 4, in: 27, out: 28}, {step: 4, in: 45, out: 44}, 194 {step: 5, in: 62, out: 60}, {step: 5, in: 63, out: 64}, {step: 5, in: 59, out: 60}, 195 {step: 5, in: 67, out: 69}, {step: 5, in: 66, out: 64}, 196 197 {step: 1, in: -26, out: -26}, {step: 1, in: -27, out: -27}, {step: 1, in: -45, out: -45}, 198 {step: 2, in: -26, out: -26}, {step: 2, in: -27, out: -28}, {step: 2, in: -45, out: -46}, 199 {step: 3, in: -26, out: -27}, {step: 3, in: -27, out: -27}, {step: 3, in: -45, out: -45}, 200 {step: 4, in: -26, out: -28}, {step: 4, in: -27, out: -28}, {step: 4, in: -45, out: -44}, 201 {step: 5, in: -62, out: -60}, {step: 5, in: -63, out: -64}, {step: 5, in: -59, out: -60}, 202 {step: 5, in: -67, out: -69}, {step: 5, in: -66, out: -64}, 203 } 204 205 for i, test := range downTests { 206 got := QuantizeFractDown(test.in, test.step) 207 if got != test.out { 208 str := "test #%d: with step %d, input %.6f (%d) expected out %.6f (%d) but got %.6f (%d" 209 t.Fatalf(str, i, test.step, ToFloat64(test.in), test.in, ToFloat64(test.out), test.out, ToFloat64(got), got) 210 } 211 } 212 }