func TestNonsortingEncodeDecimalRand(t *testing.T) { // Test with and without tmp buffer. for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { // Test with and without appending buffer. for _, append := range [][]byte{nil, []byte("hello")} { const randomTrials = 200000 for i := 0; i < randomTrials; i++ { cur := decimal.NewDecFromFloat(rand.Float64()) enc := EncodeNonsortingDecimal(append, cur) enc = enc[len(append):] res, err := DecodeNonsortingDecimal(enc, tmp) if err != nil { t.Fatal(err) } // Make sure we decode the same value we encoded. if cur.Cmp(res) != 0 { t.Fatalf("unexpected mismatch for %v, got %v", cur, res) } // Make sure we would have overestimated the value. if est := UpperBoundNonsortingDecimalSize(cur); est < len(enc) { t.Fatalf("expected estimate of %d for %v to be greater than or equal to the encoded length, found [% x]", est, cur, enc) } } } } }
func TestEncodeDecimalRand(t *testing.T) { // Test both directions. for _, dir := range []Direction{Ascending, Descending} { var prev *inf.Dec var prevEnc []byte // Test with and without tmp buffer. for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { // Test with and without appending buffer. for _, append := range [][]byte{nil, []byte("hello")} { const randomTrials = 50000 for i := 0; i < randomTrials; i++ { cur := decimal.NewDecFromFloat(rand.Float64()) var enc []byte var res *inf.Dec var err error if dir == Ascending { enc = EncodeDecimalAscending(append, cur) enc = enc[len(append):] _, res, err = DecodeDecimalAscending(enc, tmp) } else { enc = EncodeDecimalDescending(append, cur) enc = enc[len(append):] _, res, err = DecodeDecimalDescending(enc, tmp) } if err != nil { t.Fatal(err) } // Make sure we decode the same value we encoded. if cur.Cmp(res) != 0 { t.Fatalf("unexpected mismatch for %v, got %v", cur, res) } // Make sure lexicographical sorting is consistent. if prev != nil { bytesCmp := bytes.Compare(prevEnc, enc) cmpType := "same" if dir == Descending { bytesCmp *= -1 cmpType = "inverse" } if decCmp := prev.Cmp(cur); decCmp != bytesCmp { t.Fatalf("expected [% x] to compare to [% x] the %s way that %v compares to %v", prevEnc, enc, cmpType, prev, cur) } } prev = cur prevEnc = enc } } } } }
func BenchmarkEncodeDecimal(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([]*inf.Dec, 10000) for i := range vals { vals[i] = decimal.NewDecFromFloat(rng.Float64()) } buf := make([]byte, 0, 100) b.ResetTimer() for i := 0; i < b.N; i++ { _ = EncodeDecimalAscending(buf, vals[i%len(vals)]) } }
func BenchmarkDecodeDecimal(b *testing.B) { rng, _ := randutil.NewPseudoRand() vals := make([][]byte, 10000) for i := range vals { d := decimal.NewDecFromFloat(rng.Float64()) vals[i] = EncodeDecimalAscending(nil, d) } buf := make([]byte, 0, 100) b.ResetTimer() for i := 0; i < b.N; i++ { _, _, _ = DecodeDecimalAscending(vals[i%len(vals)], buf) } }
l := left.(*DDecimal).Dec r := inf.NewDec(int64(right.(DInt)), 0) return DBool(l.Cmp(r) == 0), nil }, }, cmpArgs{EQ, intType, decimalType}: { fn: func(_ EvalContext, left Datum, right Datum) (DBool, error) { l := inf.NewDec(int64(left.(DInt)), 0) r := right.(*DDecimal).Dec return DBool(l.Cmp(&r) == 0), nil }, }, cmpArgs{EQ, decimalType, floatType}: { fn: func(_ EvalContext, left Datum, right Datum) (DBool, error) { l := left.(*DDecimal).Dec r := decimal.NewDecFromFloat(float64(right.(DFloat))) return DBool(l.Cmp(r) == 0), nil }, }, cmpArgs{EQ, floatType, decimalType}: { fn: func(_ EvalContext, left Datum, right Datum) (DBool, error) { l := decimal.NewDecFromFloat(float64(left.(DFloat))) r := right.(*DDecimal).Dec return DBool(l.Cmp(&r) == 0), nil }, }, cmpArgs{EQ, dateType, dateType}: { fn: func(_ EvalContext, left Datum, right Datum) (DBool, error) { return DBool(left.(DDate) == right.(DDate)), nil }, },
func TestEncodeDecimal(t *testing.T) { testCases := []struct { Value *inf.Dec Encoding []byte }{ {decimal.NewDecFromFloat(-math.MaxFloat64), []byte{0x04, 0x64, 0xfc, 0x60, 0x66, 0x44, 0xe4, 0x9e, 0x82, 0xc0, 0x8d, 0x0}}, {inf.NewDec(-1, -308), []byte{0x04, 0x64, 0xfd, 0x0}}, // Four duplicates to make sure -1*10^4 <= -10*10^3 <= -100*10^2 <= -1*10^4 {inf.NewDec(-1, -4), []byte{0x0c, 0xfd, 0x0}}, {inf.NewDec(-10, -3), []byte{0x0c, 0xfd, 0x0}}, {inf.NewDec(-100, -2), []byte{0x0c, 0xfd, 0x0}}, {inf.NewDec(-1, -4), []byte{0x0c, 0xfd, 0x0}}, {inf.NewDec(-9999, 0), []byte{0x0d, 0x38, 0x39, 0x00}}, {inf.NewDec(-10, -1), []byte{0x0d, 0xfd, 0x00}}, {inf.NewDec(-99, 0), []byte{0x0e, 0x39, 0x00}}, {inf.NewDec(-1, 0), []byte{0x0e, 0xfd, 0x0}}, {inf.NewDec(-123, 5), []byte{0x10, 0x1, 0xe6, 0xc3, 0x0}}, {inf.NewDec(-1, 307), []byte{0x10, 0x99, 0xeb, 0x0}}, {decimal.NewDecFromFloat(-math.SmallestNonzeroFloat64), []byte{0x10, 0xa1, 0xf5, 0x0}}, {inf.NewDec(0, 0), []byte{0x11}}, {decimal.NewDecFromFloat(math.SmallestNonzeroFloat64), []byte{0x12, 0x5e, 0xa, 0x0}}, {inf.NewDec(1, 307), []byte{0x12, 0x66, 0x14, 0x0}}, {inf.NewDec(123, 5), []byte{0x12, 0xfe, 0x19, 0x3c, 0x0}}, {inf.NewDec(123, 4), []byte{0x13, 0x03, 0x2e, 0x0}}, {inf.NewDec(123, 3), []byte{0x13, 0x19, 0x3c, 0x0}}, {inf.NewDec(1, 0), []byte{0x14, 0x02, 0x0}}, {inf.NewDec(1, -1), []byte{0x14, 0x14, 0x0}}, {inf.NewDec(12345, 3), []byte{0x14, 0x19, 0x45, 0x64, 0x0}}, {inf.NewDec(990, 1), []byte{0x14, 0xc6, 0x0}}, {inf.NewDec(990001, 4), []byte{0x14, 0xc7, 0x01, 0x02, 0x0}}, {inf.NewDec(9901, 2), []byte{0x14, 0xc7, 0x02, 0x0}}, {inf.NewDec(10, -1), []byte{0x15, 0x02, 0x0}}, {inf.NewDec(10001, 2), []byte{0x15, 0x03, 0x01, 0x02, 0x0}}, {inf.NewDec(1001, 1), []byte{0x15, 0x03, 0x01, 0x14, 0x0}}, {inf.NewDec(1234, 0), []byte{0x15, 0x19, 0x44, 0x0}}, {inf.NewDec(12345, 1), []byte{0x15, 0x19, 0x45, 0x64, 0x0}}, {inf.NewDec(9999, 0), []byte{0x15, 0xc7, 0xc6, 0x0}}, {inf.NewDec(9999000001, 6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0x02, 0x0}}, {inf.NewDec(9999000009, 6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0x12, 0x0}}, {inf.NewDec(9999000010, 6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0x14, 0x0}}, {inf.NewDec(9999000090, 6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0xb4, 0x0}}, {inf.NewDec(9999000099, 6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0xc6, 0x0}}, {inf.NewDec(99990001, 4), []byte{0x15, 0xc7, 0xc7, 0x01, 0x02, 0x0}}, {inf.NewDec(9999001, 3), []byte{0x15, 0xc7, 0xc7, 0x01, 0x14, 0x0}}, {inf.NewDec(999901, 2), []byte{0x15, 0xc7, 0xc7, 0x02, 0x0}}, {inf.NewDec(99991, 1), []byte{0x15, 0xc7, 0xc7, 0x14, 0x0}}, {inf.NewDec(10000, 0), []byte{0x16, 0x02, 0x0}}, {inf.NewDec(10001, 0), []byte{0x16, 0x03, 0x01, 0x02, 0x0}}, {inf.NewDec(12345, 0), []byte{0x16, 0x03, 0x2f, 0x5a, 0x0}}, {inf.NewDec(123450, 0), []byte{0x16, 0x19, 0x45, 0x64, 0x0}}, {inf.NewDec(1, -308), []byte{0x1e, 0x9b, 0x2, 0x0}}, {decimal.NewDecFromFloat(math.MaxFloat64), []byte{0x1e, 0x9b, 0x3, 0x9f, 0x99, 0xbb, 0x1b, 0x61, 0x7d, 0x3f, 0x72, 0x0}}, } var lastEncoded []byte for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { tmp = tmp[:0] for _, dir := range []Direction{Ascending, Descending} { for i, c := range testCases { var enc []byte var err error var dec *inf.Dec if dir == Ascending { enc = EncodeDecimalAscending(nil, c.Value) _, dec, err = DecodeDecimalAscending(enc, tmp) } else { enc = EncodeDecimalDescending(nil, c.Value) _, dec, err = DecodeDecimalDescending(enc, tmp) } if dir == Ascending && !bytes.Equal(enc, c.Encoding) { t.Errorf("unexpected mismatch for %s. expected [% x], got [% x]", c.Value, c.Encoding, enc) } if i > 0 { if (bytes.Compare(lastEncoded, enc) > 0 && dir == Ascending) || (bytes.Compare(lastEncoded, enc) < 0 && dir == Descending) { t.Errorf("%v: expected [% x] to be less than or equal to [% x]", c.Value, testCases[i-1].Encoding, enc) } } if err != nil { t.Error(err) continue } if dec.Cmp(c.Value) != 0 { t.Errorf("%d unexpected mismatch for %v. got %v", i, c.Value, dec) } lastEncoded = enc } // Test that appending the decimal to an existing buffer works. var enc []byte var dec *inf.Dec other := inf.NewDec(123, 2) if dir == Ascending { enc = EncodeDecimalAscending([]byte("hello"), other) _, dec, _ = DecodeDecimalAscending(enc[5:], tmp) } else { enc = EncodeDecimalDescending([]byte("hello"), other) _, dec, _ = DecodeDecimalDescending(enc[5:], tmp) } if dec.Cmp(other) != 0 { t.Errorf("unexpected mismatch for %v. got %v", 1.23, other) } } } }
func TestNonsortingEncodeDecimal(t *testing.T) { testCases := []struct { Value *inf.Dec Encoding []byte }{ {inf.NewDec(-99122, -99999), []byte{0x1a, 0xf8, 0x01, 0x86, 0xa4, 0x01, 0x83, 0x32}}, // Three duplicates to make sure -13*10^1000 <= -130*10^999 <= -13*10^1000 {inf.NewDec(-13, -1000), []byte{0x1a, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(-130, -999), []byte{0x1a, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(-13, -1000), []byte{0x1a, 0xf7, 0x03, 0xea, 0x0d}}, {decimal.NewDecFromFloat(-math.MaxFloat64), []byte{0x1a, 0xf7, 0x01, 0x35, 0x3f, 0xdd, 0xec, 0x7f, 0x2f, 0xaf, 0x35}}, {inf.NewDec(-130, -100), []byte{0x1a, 0xef, 0x0d}}, {inf.NewDec(-13, 0), []byte{0x1a, 0x8a, 0x0d}}, {inf.NewDec(-11, 0), []byte{0x1a, 0x8a, 0x0b}}, {inf.NewDec(-1, 0), []byte{0x1a, 0x89, 0x01}}, {inf.NewDec(-8, 1), []byte{0x25, 0x08}}, {inf.NewDec(-1, 1), []byte{0x25, 0x01}}, {inf.NewDec(-11, 4), []byte{0x26, 0x8a, 0x0b}}, {inf.NewDec(-11, 6), []byte{0x26, 0x8c, 0x0b}}, {decimal.NewDecFromFloat(-math.SmallestNonzeroFloat64), []byte{0x26, 0xf7, 0x01, 0x43, 0x05}}, {inf.NewDec(-11, 66666), []byte{0x26, 0xf8, 0x01, 0x04, 0x68, 0x0b}}, {inf.NewDec(0, 0), []byte{0x27}}, {decimal.NewDecFromFloat(math.SmallestNonzeroFloat64), []byte{0x28, 0xf7, 0x01, 0x43, 0x05}}, {inf.NewDec(11, 6), []byte{0x28, 0x8c, 0x0b}}, {inf.NewDec(11, 4), []byte{0x28, 0x8a, 0x0b}}, {inf.NewDec(1, 1), []byte{0x29, 0x01}}, {inf.NewDec(12345, 5), []byte{0x29, 0x30, 0x39}}, {inf.NewDec(8, 1), []byte{0x29, 0x08}}, {inf.NewDec(1, 0), []byte{0x34, 0x89, 0x01}}, {inf.NewDec(11, 0), []byte{0x34, 0x8a, 0x0b}}, {inf.NewDec(13, 0), []byte{0x34, 0x8a, 0x0d}}, // Note that this does not sort correctly! {inf.NewDec(255, 0), []byte{0x34, 0x8b, 0xff}}, {inf.NewDec(256, 0), []byte{0x34, 0x8b, 0x01, 0x00}}, {decimal.NewDecFromFloat(math.MaxFloat64), []byte{0x34, 0xf7, 0x01, 0x35, 0x3f, 0xdd, 0xec, 0x7f, 0x2f, 0xaf, 0x35}}, // Four duplicates to make sure 13*10^1000 <= 130*10^999 <= 1300*10^998 <= 13*10^1000 {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(130, -999), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(1300, -998), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(99122, -99999), []byte{0x34, 0xf8, 0x01, 0x86, 0xa4, 0x01, 0x83, 0x32}}, {inf.NewDec(99122839898321208, -99999), []byte{0x34, 0xf8, 0x01, 0x86, 0xb0, 0x01, 0x60, 0x27, 0xb2, 0x9d, 0x44, 0x71, 0x38}}, } for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { for i, c := range testCases { enc := EncodeNonsortingDecimal(nil, c.Value) dec, err := DecodeNonsortingDecimal(enc, tmp) if err != nil { t.Error(err) continue } if !bytes.Equal(enc, c.Encoding) { t.Errorf("unexpected mismatch for %s. expected [% x], got [% x]", c.Value, c.Encoding, enc) } if dec.Cmp(c.Value) != 0 { t.Errorf("%d unexpected mismatch for %v. got %v", i, c.Value, dec) } } // Test that appending the decimal to an existing buffer works. other := inf.NewDec(123, 2) enc := EncodeNonsortingDecimal([]byte("hello"), other) dec, err := DecodeNonsortingDecimal(enc[5:], tmp) if err != nil { t.Error(err) continue } if dec.Cmp(other) != 0 { t.Errorf("unexpected mismatch for %v. got %v", 1.23, other) } } }
func TestEncodeDecimal(t *testing.T) { testCases := []struct { Value *inf.Dec Encoding []byte }{ {inf.NewDec(-99122, -99999), []byte{0x1a, 0x86, 0x3c, 0xad, 0x38, 0xe6, 0xd7, 0x00}}, // Three duplicates to make sure -13*10^1000 <= -130*10^999 <= -13*10^1000 {inf.NewDec(-13, -1000), []byte{0x1a, 0x86, 0xfe, 0x0a, 0xe5, 0x00}}, {inf.NewDec(-130, -999), []byte{0x1a, 0x86, 0xfe, 0x0a, 0xe5, 0x00}}, {inf.NewDec(-13, -1000), []byte{0x1a, 0x86, 0xfe, 0x0a, 0xe5, 0x00}}, {decimal.NewDecFromFloat(-math.MaxFloat64), []byte{0x1a, 0x87, 0x64, 0xfc, 0x60, 0x66, 0x44, 0xe4, 0x9e, 0x82, 0xc0, 0x8d, 0x00}}, {inf.NewDec(-130, -100), []byte{0x1a, 0x87, 0xcb, 0xfc, 0xc3, 0x00}}, {inf.NewDec(-13, 0), []byte{0x24, 0xe5, 0x00}}, {inf.NewDec(-11, 0), []byte{0x24, 0xe9, 0x00}}, {mustDecimal("-10.123456789"), []byte{0x24, 0xea, 0xe6, 0xba, 0x8e, 0x62, 0x4b, 0x00}}, {mustDecimal("-10"), []byte{0x24, 0xeb, 0x00}}, {mustDecimal("-9.123456789"), []byte{0x24, 0xec, 0xe6, 0xba, 0x8e, 0x62, 0x4b, 0x00}}, {mustDecimal("-9"), []byte{0x24, 0xed, 0x00}}, {mustDecimal("-1.1"), []byte{0x24, 0xfc, 0xeb, 0x00}}, {inf.NewDec(-1, 0), []byte{0x24, 0xfd, 0x00}}, {inf.NewDec(-8, 1), []byte{0x25, 0x5f, 0x00}}, {inf.NewDec(-1, 1), []byte{0x25, 0xeb, 0x00}}, {mustDecimal("-.09"), []byte{0x25, 0xed, 0x00}}, {mustDecimal("-.054321"), []byte{0x25, 0xf4, 0xa8, 0xd5, 0x00}}, {mustDecimal("-.012"), []byte{0x25, 0xfc, 0xd7, 0x00}}, {inf.NewDec(-11, 4), []byte{0x26, 0x89, 0xe9, 0x00}}, {inf.NewDec(-11, 6), []byte{0x26, 0x8a, 0xe9, 0x00}}, {decimal.NewDecFromFloat(-math.SmallestNonzeroFloat64), []byte{0x26, 0xf6, 0xa1, 0xf5, 0x00}}, {inf.NewDec(-11, 66666), []byte{0x26, 0xf7, 0x82, 0x34, 0xe9, 0x00}}, {inf.NewDec(0, 0), []byte{0x27}}, {decimal.NewDecFromFloat(math.SmallestNonzeroFloat64), []byte{0x28, 0x87, 0x5e, 0x0a, 0x00}}, {inf.NewDec(11, 6), []byte{0x28, 0x87, 0xfd, 0x16, 0x00}}, {inf.NewDec(11, 4), []byte{0x28, 0x87, 0xfe, 0x16, 0x00}}, {inf.NewDec(1, 1), []byte{0x29, 0x14, 0x00}}, {inf.NewDec(8, 1), []byte{0x29, 0xa0, 0x00}}, {inf.NewDec(1, 0), []byte{0x2a, 0x02, 0x00}}, {mustDecimal("1.1"), []byte{0x2a, 0x03, 0x14, 0x00}}, {inf.NewDec(11, 0), []byte{0x2a, 0x16, 0x00}}, {inf.NewDec(13, 0), []byte{0x2a, 0x1a, 0x00}}, {decimal.NewDecFromFloat(math.MaxFloat64), []byte{0x34, 0xf6, 0x9b, 0x03, 0x9f, 0x99, 0xbb, 0x1b, 0x61, 0x7d, 0x3f, 0x72, 0x00}}, // Four duplicates to make sure 13*10^1000 <= 130*10^999 <= 1300*10^998 <= 13*10^1000 {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(130, -999), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(1300, -998), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(99122, -99999), []byte{0x34, 0xf7, 0xc3, 0x52, 0xc7, 0x19, 0x28, 0x00}}, {inf.NewDec(99122839898321208, -99999), []byte{0x34, 0xf7, 0xc3, 0x58, 0xc7, 0x19, 0x39, 0x4f, 0xb3, 0xa7, 0x2b, 0x29, 0xa0, 0x00}}, } var lastEncoded []byte for _, dir := range []Direction{Ascending, Descending} { for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { for i, c := range testCases { var enc []byte var err error var dec *inf.Dec if dir == Ascending { enc = EncodeDecimalAscending(nil, c.Value) _, dec, err = DecodeDecimalAscending(enc, tmp) } else { enc = EncodeDecimalDescending(nil, c.Value) _, dec, err = DecodeDecimalDescending(enc, tmp) } if dir == Ascending && !bytes.Equal(enc, c.Encoding) { t.Errorf("unexpected mismatch for %s. expected [% x], got [% x]", c.Value, c.Encoding, enc) } if i > 0 { if (bytes.Compare(lastEncoded, enc) > 0 && dir == Ascending) || (bytes.Compare(lastEncoded, enc) < 0 && dir == Descending) { t.Errorf("%v: expected [% x] to be less than or equal to [% x]", c.Value, testCases[i-1].Encoding, enc) } } if err != nil { t.Error(err) continue } if dec.Cmp(c.Value) != 0 { t.Errorf("%d unexpected mismatch for %v. got %v", i, c.Value, dec) } lastEncoded = enc } // Test that appending the decimal to an existing buffer works. var enc []byte var dec *inf.Dec other := inf.NewDec(123, 2) if dir == Ascending { enc = EncodeDecimalAscending([]byte("hello"), other) _, dec, _ = DecodeDecimalAscending(enc[5:], tmp) } else { enc = EncodeDecimalDescending([]byte("hello"), other) _, dec, _ = DecodeDecimalDescending(enc[5:], tmp) } if dec.Cmp(other) != 0 { t.Errorf("unexpected mismatch for %v. got %v", 1.23, other) } } } }
func TestEncodeDecimal(t *testing.T) { testCases := []struct { Value *inf.Dec Encoding []byte }{ {inf.NewDec(-99122, -99999), []byte{0x09, 0x05, 0xfe, 0x79, 0x5b, 0xfe, 0x7c, 0xcd, 0x00}}, // Three duplicates to make sure -13*10^1000 <= -130*10^999 <= -13*10^1000 {inf.NewDec(-13, -1000), []byte{0x09, 0x0c, 0x05, 0xf2, 0x00}}, {inf.NewDec(-130, -999), []byte{0x09, 0x0c, 0x05, 0xf2, 0x00}}, {inf.NewDec(-13, -1000), []byte{0x09, 0x0c, 0x05, 0xf2, 0x00}}, {decimal.NewDecFromFloat(-math.MaxFloat64), []byte{0x09, 0x0e, 0xba, 0xc0, 0x22, 0x13, 0x80, 0xd0, 0x50, 0xca, 0x00}}, {inf.NewDec(-130, -100), []byte{0x09, 0x98, 0xf2, 0x00}}, {inf.NewDec(-13, 0), []byte{0x09, 0xfd, 0xf2, 0x00}}, {inf.NewDec(-11, 0), []byte{0x09, 0xfd, 0xf4, 0x00}}, {inf.NewDec(-1, 0), []byte{0x09, 0xfe, 0xfe, 0x00}}, {inf.NewDec(-8, 1), []byte{0x0a, 0xf7, 0x00}}, {inf.NewDec(-1, 1), []byte{0x0a, 0xfe, 0x00}}, {inf.NewDec(-11, 4), []byte{0x0b, 0x02, 0xf4, 0x00}}, {inf.NewDec(-11, 6), []byte{0x0b, 0x04, 0xf4, 0x00}}, {decimal.NewDecFromFloat(-math.SmallestNonzeroFloat64), []byte{0x0b, 0xf1, 0x53, 0xfa, 0x00}}, {inf.NewDec(-11, 66666), []byte{0x0b, 0xf9, 0xfb, 0x78, 0xf4, 0x00}}, {inf.NewDec(0, 0), []byte{0x0c}}, {decimal.NewDecFromFloat(math.SmallestNonzeroFloat64), []byte{0x0d, 0x0e, 0xac, 0x05, 0x00}}, {inf.NewDec(11, 6), []byte{0x0d, 0xfb, 0x0b, 0x00}}, {inf.NewDec(11, 4), []byte{0x0d, 0xfd, 0x0b, 0x00}}, {inf.NewDec(1, 1), []byte{0x0e, 0x01, 0x00}}, {inf.NewDec(8, 1), []byte{0x0e, 0x08, 0x00}}, {inf.NewDec(1, 0), []byte{0x0f, 0x01, 0x01, 0x00}}, {inf.NewDec(11, 0), []byte{0x0f, 0x02, 0x0b, 0x00}}, {inf.NewDec(13, 0), []byte{0x0f, 0x02, 0x0d, 0x00}}, {decimal.NewDecFromFloat(math.MaxFloat64), []byte{0x0f, 0xf1, 0x45, 0x3f, 0xdd, 0xec, 0x7f, 0x2f, 0xaf, 0x35, 0x00}}, // Four duplicates to make sure 13*10^1000 <= 130*10^999 <= 1300*10^998 <= 13*10^1000 {inf.NewDec(13, -1000), []byte{0x0f, 0xf3, 0xfa, 0x0d, 0x00}}, {inf.NewDec(130, -999), []byte{0x0f, 0xf3, 0xfa, 0x0d, 0x00}}, {inf.NewDec(1300, -998), []byte{0x0f, 0xf3, 0xfa, 0x0d, 0x00}}, {inf.NewDec(13, -1000), []byte{0x0f, 0xf3, 0xfa, 0x0d, 0x00}}, {inf.NewDec(99122, -99999), []byte{0x0f, 0xfa, 0x01, 0x86, 0xa4, 0x01, 0x83, 0x32, 0x00}}, {inf.NewDec(99122839898321208, -99999), []byte{0x0f, 0xfa, 0x01, 0x86, 0xb0, 0x01, 0x60, 0x27, 0xb2, 0x9d, 0x44, 0x71, 0x38, 0x00}}, } var lastEncoded []byte for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { tmp = tmp[:0] for _, dir := range []Direction{Ascending, Descending} { for i, c := range testCases { var enc []byte var err error var dec *inf.Dec if dir == Ascending { enc = EncodeDecimalAscending(nil, c.Value) _, dec, err = DecodeDecimalAscending(enc, tmp) } else { enc = EncodeDecimalDescending(nil, c.Value) _, dec, err = DecodeDecimalDescending(enc, tmp) } if dir == Ascending && !bytes.Equal(enc, c.Encoding) { t.Errorf("unexpected mismatch for %s. expected [% x], got [% x]", c.Value, c.Encoding, enc) } if i > 0 { if (bytes.Compare(lastEncoded, enc) > 0 && dir == Ascending) || (bytes.Compare(lastEncoded, enc) < 0 && dir == Descending) { t.Errorf("%v: expected [% x] to be less than or equal to [% x]", c.Value, testCases[i-1].Encoding, enc) } } if err != nil { t.Error(err) continue } if dec.Cmp(c.Value) != 0 { t.Errorf("%d unexpected mismatch for %v. got %v", i, c.Value, dec) } lastEncoded = enc } // Test that appending the decimal to an existing buffer works. var enc []byte var dec *inf.Dec other := inf.NewDec(123, 2) if dir == Ascending { enc = EncodeDecimalAscending([]byte("hello"), other) _, dec, _ = DecodeDecimalAscending(enc[5:], tmp) } else { enc = EncodeDecimalDescending([]byte("hello"), other) _, dec, _ = DecodeDecimalDescending(enc[5:], tmp) } if dec.Cmp(other) != 0 { t.Errorf("unexpected mismatch for %v. got %v", 1.23, other) } } } }
// randDecimal generates a random decimal with exponent in the // range [minExp, maxExp]. func randDecimal(rng *rand.Rand, minExp, maxExp int) *inf.Dec { exp := randutil.RandIntInRange(rng, minExp, maxExp+1) // Transform random float in [0, 1) to [-1, 1) and multiply by 10^exp. floatVal := (rng.Float64()*2 - 1) * math.Pow10(exp) return decimal.NewDecFromFloat(floatVal) }
func TestNonsortingEncodeDecimal(t *testing.T) { testCases := []struct { Value *inf.Dec Encoding []byte }{ {inf.NewDec(-99122, -99999), []byte{0x1a, 0xf8, 0x01, 0x86, 0xa4, 0x01, 0x83, 0x32}}, // Three duplicates to make sure -13*10^1000 <= -130*10^999 <= -13*10^1000 {inf.NewDec(-13, -1000), []byte{0x1a, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(-130, -999), []byte{0x1a, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(-13, -1000), []byte{0x1a, 0xf7, 0x03, 0xea, 0x0d}}, {decimal.NewDecFromFloat(-math.MaxFloat64), []byte{0x1a, 0xf7, 0x01, 0x35, 0x3f, 0xdd, 0xec, 0x7f, 0x2f, 0xaf, 0x35}}, {inf.NewDec(-130, -100), []byte{0x1a, 0xef, 0x0d}}, {inf.NewDec(-13, 0), []byte{0x1a, 0x8a, 0x0d}}, {inf.NewDec(-11, 0), []byte{0x1a, 0x8a, 0x0b}}, {inf.NewDec(-1, 0), []byte{0x1a, 0x89, 0x01}}, {inf.NewDec(-8, 1), []byte{0x25, 0x08}}, {inf.NewDec(-1, 1), []byte{0x25, 0x01}}, {inf.NewDec(-11, 4), []byte{0x26, 0x8a, 0x0b}}, {inf.NewDec(-11, 6), []byte{0x26, 0x8c, 0x0b}}, {decimal.NewDecFromFloat(-math.SmallestNonzeroFloat64), []byte{0x26, 0xf7, 0x01, 0x43, 0x05}}, {inf.NewDec(-11, 66666), []byte{0x26, 0xf8, 0x01, 0x04, 0x68, 0x0b}}, {inf.NewDec(0, 0), []byte{0x27}}, {decimal.NewDecFromFloat(math.SmallestNonzeroFloat64), []byte{0x28, 0xf7, 0x01, 0x43, 0x05}}, {inf.NewDec(11, 6), []byte{0x28, 0x8c, 0x0b}}, {inf.NewDec(11, 4), []byte{0x28, 0x8a, 0x0b}}, {inf.NewDec(1, 1), []byte{0x29, 0x01}}, {inf.NewDec(12345, 5), []byte{0x29, 0x30, 0x39}}, {inf.NewDec(8, 1), []byte{0x29, 0x08}}, {inf.NewDec(1, 0), []byte{0x34, 0x89, 0x01}}, {inf.NewDec(11, 0), []byte{0x34, 0x8a, 0x0b}}, {inf.NewDec(13, 0), []byte{0x34, 0x8a, 0x0d}}, // Note that this does not sort correctly! {inf.NewDec(255, 0), []byte{0x34, 0x8b, 0xff}}, {inf.NewDec(256, 0), []byte{0x34, 0x8b, 0x01, 0x00}}, {decimal.NewDecFromFloat(math.MaxFloat64), []byte{0x34, 0xf7, 0x01, 0x35, 0x3f, 0xdd, 0xec, 0x7f, 0x2f, 0xaf, 0x35}}, // Four duplicates to make sure 13*10^1000 <= 130*10^999 <= 1300*10^998 <= 13*10^1000 {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(130, -999), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(1300, -998), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x03, 0xea, 0x0d}}, {inf.NewDec(99122, -99999), []byte{0x34, 0xf8, 0x01, 0x86, 0xa4, 0x01, 0x83, 0x32}}, {inf.NewDec(99122839898321208, -99999), []byte{0x34, 0xf8, 0x01, 0x86, 0xb0, 0x01, 0x60, 0x27, 0xb2, 0x9d, 0x44, 0x71, 0x38}}, } rng, _ := randutil.NewPseudoRand() for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { for i, c := range testCases { enc := EncodeNonsortingDecimal(nil, c.Value) dec, err := DecodeNonsortingDecimal(enc, tmp) if err != nil { t.Error(err) continue } if !bytes.Equal(enc, c.Encoding) { t.Errorf("unexpected mismatch for %s. expected [% x], got [% x]", c.Value, c.Encoding, enc) } if dec.Cmp(c.Value) != 0 { t.Errorf("%d unexpected mismatch for %v. got %v", i, c.Value, dec) } // Test that appending the decimal to an existing buffer works. It // is important to test with various values, slice lengths, and // capacities because the various encoding paths try to use any // spare capacity to avoid allocations. for trials := 0; trials < 5; trials++ { orig := randBuf(rng, 30) origLen := len(orig) bufCap := origLen + rng.Intn(30) buf := make([]byte, origLen, bufCap) copy(buf, orig) enc := EncodeNonsortingDecimal(buf, c.Value) dec, err := DecodeNonsortingDecimal(enc[origLen:], tmp) if err != nil { t.Fatal(err) } if dec.Cmp(c.Value) != 0 { t.Errorf("unexpected mismatch for %v. got %v", c.Value, dec) } // Verify the existing values weren't modified. for i := range orig { if enc[i] != orig[i] { t.Errorf("existing byte %d changed after encoding (from %d to %d)", i, orig[i], enc[i]) } } } } } }
func TestEncodeDecimal(t *testing.T) { testCases := []struct { Value *inf.Dec Encoding []byte }{ {inf.NewDec(-99122, -99999), []byte{0x1a, 0x86, 0x3c, 0xad, 0x38, 0xe6, 0xd7, 0x00}}, // Three duplicates to make sure -13*10^1000 <= -130*10^999 <= -13*10^1000 {inf.NewDec(-13, -1000), []byte{0x1a, 0x86, 0xfe, 0x0a, 0xe5, 0x00}}, {inf.NewDec(-130, -999), []byte{0x1a, 0x86, 0xfe, 0x0a, 0xe5, 0x00}}, {inf.NewDec(-13, -1000), []byte{0x1a, 0x86, 0xfe, 0x0a, 0xe5, 0x00}}, {decimal.NewDecFromFloat(-math.MaxFloat64), []byte{0x1a, 0x87, 0x64, 0xfc, 0x60, 0x66, 0x44, 0xe4, 0x9e, 0x82, 0xc0, 0x8d, 0x00}}, {inf.NewDec(-130, -100), []byte{0x1a, 0x87, 0xcb, 0xfc, 0xc3, 0x00}}, {inf.NewDec(-13, 0), []byte{0x24, 0xe5, 0x00}}, {inf.NewDec(-11, 0), []byte{0x24, 0xe9, 0x00}}, {mustDecimal("-10.123456789"), []byte{0x24, 0xea, 0xe6, 0xba, 0x8e, 0x62, 0x4b, 0x00}}, {mustDecimal("-10"), []byte{0x24, 0xeb, 0x00}}, {mustDecimal("-9.123456789"), []byte{0x24, 0xec, 0xe6, 0xba, 0x8e, 0x62, 0x4b, 0x00}}, {mustDecimal("-9"), []byte{0x24, 0xed, 0x00}}, {mustDecimal("-1.1"), []byte{0x24, 0xfc, 0xeb, 0x00}}, {inf.NewDec(-1, 0), []byte{0x24, 0xfd, 0x00}}, {inf.NewDec(-8, 1), []byte{0x25, 0x5f, 0x00}}, {inf.NewDec(-1, 1), []byte{0x25, 0xeb, 0x00}}, {mustDecimal("-.09"), []byte{0x25, 0xed, 0x00}}, {mustDecimal("-.054321"), []byte{0x25, 0xf4, 0xa8, 0xd5, 0x00}}, {mustDecimal("-.012"), []byte{0x25, 0xfc, 0xd7, 0x00}}, {inf.NewDec(-11, 4), []byte{0x26, 0x89, 0xe9, 0x00}}, {inf.NewDec(-11, 6), []byte{0x26, 0x8a, 0xe9, 0x00}}, {decimal.NewDecFromFloat(-math.SmallestNonzeroFloat64), []byte{0x26, 0xf6, 0xa1, 0xf5, 0x00}}, {inf.NewDec(-11, 66666), []byte{0x26, 0xf7, 0x82, 0x34, 0xe9, 0x00}}, {inf.NewDec(0, 0), []byte{0x27}}, {decimal.NewDecFromFloat(math.SmallestNonzeroFloat64), []byte{0x28, 0x87, 0x5e, 0x0a, 0x00}}, {inf.NewDec(11, 6), []byte{0x28, 0x87, 0xfd, 0x16, 0x00}}, {inf.NewDec(11, 4), []byte{0x28, 0x87, 0xfe, 0x16, 0x00}}, {inf.NewDec(1, 1), []byte{0x29, 0x14, 0x00}}, {inf.NewDec(8, 1), []byte{0x29, 0xa0, 0x00}}, {inf.NewDec(1, 0), []byte{0x2a, 0x02, 0x00}}, {mustDecimal("1.1"), []byte{0x2a, 0x03, 0x14, 0x00}}, {inf.NewDec(11, 0), []byte{0x2a, 0x16, 0x00}}, {inf.NewDec(13, 0), []byte{0x2a, 0x1a, 0x00}}, {decimal.NewDecFromFloat(math.MaxFloat64), []byte{0x34, 0xf6, 0x9b, 0x03, 0x9f, 0x99, 0xbb, 0x1b, 0x61, 0x7d, 0x3f, 0x72, 0x00}}, // Four duplicates to make sure 13*10^1000 <= 130*10^999 <= 1300*10^998 <= 13*10^1000 {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(130, -999), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(1300, -998), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(13, -1000), []byte{0x34, 0xf7, 0x01, 0xf5, 0x1a, 0x00}}, {inf.NewDec(99122, -99999), []byte{0x34, 0xf7, 0xc3, 0x52, 0xc7, 0x19, 0x28, 0x00}}, {inf.NewDec(99122839898321208, -99999), []byte{0x34, 0xf7, 0xc3, 0x58, 0xc7, 0x19, 0x39, 0x4f, 0xb3, 0xa7, 0x2b, 0x29, 0xa0, 0x00}}, } rng, _ := randutil.NewPseudoRand() var lastEncoded []byte for _, dir := range []Direction{Ascending, Descending} { for _, tmp := range [][]byte{nil, make([]byte, 0, 100)} { for i, c := range testCases { enc := encodeDecimalWithDir(dir, nil, c.Value) _, dec := decodeDecimalWithDir(t, dir, enc, tmp) if dir == Ascending && !bytes.Equal(enc, c.Encoding) { t.Errorf("unexpected mismatch for %s. expected [% x], got [% x]", c.Value, c.Encoding, enc) } if i > 0 { if (bytes.Compare(lastEncoded, enc) > 0 && dir == Ascending) || (bytes.Compare(lastEncoded, enc) < 0 && dir == Descending) { t.Errorf("%v: expected [% x] to be less than or equal to [% x]", c.Value, testCases[i-1].Encoding, enc) } } testPeekLength(t, enc) if dec.Cmp(c.Value) != 0 { t.Errorf("%d unexpected mismatch for %v. got %v", i, c.Value, dec) } lastEncoded = enc // Test that appending the decimal to an existing buffer works. It // is important to test with various values, slice lengths, and // capacities because the various encoding paths try to use any // spare capacity to avoid allocations. for trials := 0; trials < 5; trials++ { orig := randBuf(rng, 30) origLen := len(orig) bufCap := origLen + rng.Intn(30) buf := make([]byte, origLen, bufCap) copy(buf, orig) enc := encodeDecimalWithDir(dir, buf, c.Value) // Append some random bytes enc = append(enc, randBuf(rng, 20)...) _, dec := decodeDecimalWithDir(t, dir, enc[origLen:], tmp) if dec.Cmp(c.Value) != 0 { t.Errorf("unexpected mismatch for %v. got %v", c.Value, dec) } // Verify the existing values weren't modified. for i := range orig { if enc[i] != orig[i] { t.Errorf("existing byte %d changed after encoding (from %d to %d)", i, orig[i], enc[i]) } } } } } } }