Example #1
0
func floatOrDecimalBuiltin2(f func(float64, float64) (Datum, error)) []builtin {
	return []builtin{
		{
			types:      argTypes{floatType, floatType},
			returnType: typeFloat,
			fn: func(_ EvalContext, args DTuple) (Datum, error) {
				return f(float64(args[0].(DFloat)),
					float64(args[1].(DFloat)))
			},
		}, {
			types:      argTypes{decimalType, decimalType},
			returnType: typeDecimal,
			fn: func(_ EvalContext, args DTuple) (Datum, error) {
				v1, _ := args[0].(DDecimal).Float64()
				v2, _ := args[1].(DDecimal).Float64()
				r, err := f(v1, v2)
				if err != nil {
					return r, err
				}
				rf := float64(r.(DFloat))
				if math.IsNaN(rf) || math.IsInf(rf, 0) {
					// TODO(nvanbenschoten) NaN semmantics should be introduced
					// into the decimal library to support it here.
					return nil, fmt.Errorf("decimal does not support NaN")
				}
				return DDecimal{Decimal: decimal.NewFromFloat(rf)}, nil
			},
		},
	}
}
Example #2
0
func BenchmarkEncodeDecimal(b *testing.B) {
	rng, _ := randutil.NewPseudoRand()

	vals := make([]decimal.Decimal, 10000)
	for i := range vals {
		vals[i] = decimal.NewFromFloat(rng.Float64())
	}

	buf := make([]byte, 0, 100)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = EncodeDecimalAscending(buf, vals[i%len(vals)])
	}
}
Example #3
0
func BenchmarkDecodeDecimal(b *testing.B) {
	rng, _ := randutil.NewPseudoRand()

	vals := make([][]byte, 10000)
	for i := range vals {
		d := decimal.NewFromFloat(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)
	}
}
Example #4
0
func TestEncodeDecimal(t *testing.T) {
	testCases := []struct {
		Value    decimal.Decimal
		Encoding []byte
	}{
		{decimal.NewFromFloat(-math.MaxFloat64), []byte{0x04, 0x64, 0xfc, 0x60, 0x66, 0x44, 0xe4, 0x9e, 0x82, 0xc0, 0x8d, 0x0}},
		{decimal.New(-1, 308), []byte{0x04, 0x64, 0xfd, 0x0}},
		// Four duplicates to make sure -1*10^4 <= -10*10^3 <= -100*10^2 <= -1*10^4
		{decimal.New(-1, 4), []byte{0x0c, 0xfd, 0x0}},
		{decimal.New(-10, 3), []byte{0x0c, 0xfd, 0x0}},
		{decimal.New(-100, 2), []byte{0x0c, 0xfd, 0x0}},
		{decimal.New(-1, 4), []byte{0x0c, 0xfd, 0x0}},
		{decimal.New(-9999, 0), []byte{0x0d, 0x38, 0x39, 0x00}},
		{decimal.New(-10, 1), []byte{0x0d, 0xfd, 0x00}},
		{decimal.New(-99, 0), []byte{0x0e, 0x39, 0x00}},
		{decimal.New(-1, 0), []byte{0x0e, 0xfd, 0x0}},
		{decimal.New(-123, -5), []byte{0x10, 0x1, 0xe6, 0xc3, 0x0}},
		{decimal.New(-1, -307), []byte{0x10, 0x99, 0xeb, 0x0}},
		{decimal.NewFromFloat(-math.SmallestNonzeroFloat64), []byte{0x10, 0xa1, 0xf5, 0x0}},
		{decimal.New(0, 0), []byte{0x11}},
		{decimal.NewFromFloat(math.SmallestNonzeroFloat64), []byte{0x12, 0x5e, 0xa, 0x0}},
		{decimal.New(1, -307), []byte{0x12, 0x66, 0x14, 0x0}},
		{decimal.New(123, -5), []byte{0x12, 0xfe, 0x19, 0x3c, 0x0}},
		{decimal.New(123, -4), []byte{0x13, 0x03, 0x2e, 0x0}},
		{decimal.New(123, -3), []byte{0x13, 0x19, 0x3c, 0x0}},
		{decimal.New(1, 0), []byte{0x14, 0x02, 0x0}},
		{decimal.New(1, 1), []byte{0x14, 0x14, 0x0}},
		{decimal.New(12345, -3), []byte{0x14, 0x19, 0x45, 0x64, 0x0}},
		{decimal.New(990, -1), []byte{0x14, 0xc6, 0x0}},
		{decimal.New(990001, -4), []byte{0x14, 0xc7, 0x01, 0x02, 0x0}},
		{decimal.New(9901, -2), []byte{0x14, 0xc7, 0x02, 0x0}},
		{decimal.New(10, 1), []byte{0x15, 0x02, 0x0}},
		{decimal.New(10001, -2), []byte{0x15, 0x03, 0x01, 0x02, 0x0}},
		{decimal.New(1001, -1), []byte{0x15, 0x03, 0x01, 0x14, 0x0}},
		{decimal.New(1234, 0), []byte{0x15, 0x19, 0x44, 0x0}},
		{decimal.New(12345, -1), []byte{0x15, 0x19, 0x45, 0x64, 0x0}},
		{decimal.New(9999, 0), []byte{0x15, 0xc7, 0xc6, 0x0}},
		{decimal.New(9999000001, -6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0x02, 0x0}},
		{decimal.New(9999000009, -6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0x12, 0x0}},
		{decimal.New(9999000010, -6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0x14, 0x0}},
		{decimal.New(9999000090, -6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0xb4, 0x0}},
		{decimal.New(9999000099, -6), []byte{0x15, 0xc7, 0xc7, 0x01, 0x01, 0xc6, 0x0}},
		{decimal.New(99990001, -4), []byte{0x15, 0xc7, 0xc7, 0x01, 0x02, 0x0}},
		{decimal.New(9999001, -3), []byte{0x15, 0xc7, 0xc7, 0x01, 0x14, 0x0}},
		{decimal.New(999901, -2), []byte{0x15, 0xc7, 0xc7, 0x02, 0x0}},
		{decimal.New(99991, -1), []byte{0x15, 0xc7, 0xc7, 0x14, 0x0}},
		{decimal.New(10000, 0), []byte{0x16, 0x02, 0x0}},
		{decimal.New(10001, 0), []byte{0x16, 0x03, 0x01, 0x02, 0x0}},
		{decimal.New(12345, 0), []byte{0x16, 0x03, 0x2f, 0x5a, 0x0}},
		{decimal.New(123450, 0), []byte{0x16, 0x19, 0x45, 0x64, 0x0}},
		{decimal.New(1, 308), []byte{0x1e, 0x9b, 0x2, 0x0}},
		{decimal.NewFromFloat(math.MaxFloat64), []byte{0x1e, 0x9b, 0x3, 0x9f, 0x99, 0xbb, 0x1b, 0x61, 0x7d, 0x3f, 0x72, 0x0}},
	}

	var lastEncoded []byte
	for _, dir := range []Direction{Ascending, Descending} {
		for i, c := range testCases {
			var enc []byte
			var err error
			var dec decimal.Decimal
			if dir == Ascending {
				enc = EncodeDecimalAscending(nil, c.Value)
				_, dec, err = DecodeDecimalAscending(enc, nil)
			} else {
				enc = EncodeDecimalDescending(nil, c.Value)
				_, dec, err = DecodeDecimalDescending(enc, nil)
			}
			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.Equals(c.Value) {
				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 decimal.Decimal
		other := decimal.NewFromFloat(1.23)
		if dir == Ascending {
			enc = EncodeDecimalAscending([]byte("hello"), other)
			_, dec, _ = DecodeDecimalAscending(enc[5:], nil)
		} else {
			enc = EncodeDecimalDescending([]byte("hello"), other)
			_, dec, _ = DecodeDecimalDescending(enc[5:], nil)
		}
		if !dec.Equals(other) {
			t.Errorf("unexpected mismatch for %v. got %v", 1.23, other)
		}
	}
}