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  }