Assign Numeric to *big.Rat
This commit is contained in:
committed by
Jack Christensen
parent
75446032b9
commit
ccc7cc2931
+26
@@ -369,6 +369,12 @@ func (src *Numeric) AssignTo(dst interface{}) error {
|
|||||||
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
|
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
|
||||||
}
|
}
|
||||||
*v = normalizedInt.Uint64()
|
*v = normalizedInt.Uint64()
|
||||||
|
case *big.Rat:
|
||||||
|
rat, err := src.toBigRat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Set(rat)
|
||||||
default:
|
default:
|
||||||
if nextDst, retry := GetAssignToDstType(dst); retry {
|
if nextDst, retry := GetAssignToDstType(dst); retry {
|
||||||
return src.AssignTo(nextDst)
|
return src.AssignTo(nextDst)
|
||||||
@@ -406,6 +412,26 @@ func (dst *Numeric) toBigInt() (*big.Int, error) {
|
|||||||
return num, nil
|
return num, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dst *Numeric) toBigRat() (*big.Rat, error) {
|
||||||
|
if dst.NaN {
|
||||||
|
return nil, fmt.Errorf("%v is not a number", dst)
|
||||||
|
} else if dst.InfinityModifier == Infinity {
|
||||||
|
return nil, fmt.Errorf("%v is infinity", dst)
|
||||||
|
} else if dst.InfinityModifier == NegativeInfinity {
|
||||||
|
return nil, fmt.Errorf("%v is -infinity", dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
num := new(big.Rat).SetInt(dst.Int)
|
||||||
|
if dst.Exp > 0 {
|
||||||
|
mul := new(big.Int).Exp(big10, big.NewInt(int64(dst.Exp)), nil)
|
||||||
|
num.Mul(num, new(big.Rat).SetInt(mul))
|
||||||
|
} else if dst.Exp < 0 {
|
||||||
|
mul := new(big.Int).Exp(big10, big.NewInt(int64(-dst.Exp)), nil)
|
||||||
|
num.Quo(num, new(big.Rat).SetInt(mul))
|
||||||
|
}
|
||||||
|
return num, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (src *Numeric) toFloat64() (float64, error) {
|
func (src *Numeric) toFloat64() (float64, error) {
|
||||||
if src.NaN {
|
if src.NaN {
|
||||||
return math.NaN(), nil
|
return math.NaN(), nil
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ func TestNumericAssignTo(t *testing.T) {
|
|||||||
var f64 float64
|
var f64 float64
|
||||||
var pf32 *float32
|
var pf32 *float32
|
||||||
var pf64 *float64
|
var pf64 *float64
|
||||||
|
var br = new(big.Rat)
|
||||||
|
|
||||||
simpleTests := []struct {
|
simpleTests := []struct {
|
||||||
src *pgtype.Numeric
|
src *pgtype.Numeric
|
||||||
@@ -293,6 +294,9 @@ func TestNumericAssignTo(t *testing.T) {
|
|||||||
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: &f32, expected: float32(math.Inf(1))},
|
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: &f32, expected: float32(math.Inf(1))},
|
||||||
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f64, expected: math.Inf(-1)},
|
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f64, expected: math.Inf(-1)},
|
||||||
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f32, expected: float32(math.Inf(-1))},
|
{src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f32, expected: float32(math.Inf(-1))},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(-1023), Exp: -2, Status: pgtype.Present}, dst: br, expected: big.NewRat(-1023, 100)},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(-1023), Exp: 2, Status: pgtype.Present}, dst: br, expected: big.NewRat(-102300, 1)},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(23), Exp: 0, Status: pgtype.Present}, dst: br, expected: big.NewRat(23, 1)},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range simpleTests {
|
for i, tt := range simpleTests {
|
||||||
@@ -317,6 +321,11 @@ func TestNumericAssignTo(t *testing.T) {
|
|||||||
} else if !nanExpected && dst != tt.expected {
|
} else if !nanExpected && dst != tt.expected {
|
||||||
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||||
}
|
}
|
||||||
|
case big.Rat:
|
||||||
|
if (&dstTyped).Cmp(tt.expected.(*big.Rat)) != 0 {
|
||||||
|
t.Errorf("%d: expected %v to assign %v, but result was %v",
|
||||||
|
i, tt.src, tt.expected, dst)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
if dst != tt.expected {
|
if dst != tt.expected {
|
||||||
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||||
@@ -356,6 +365,10 @@ func TestNumericAssignTo(t *testing.T) {
|
|||||||
{src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui64},
|
{src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui64},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui},
|
{src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui},
|
||||||
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: &i32},
|
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: &i32},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: br},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, NaN: true}, dst: br},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: br},
|
||||||
|
{src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: br},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range errorTests {
|
for i, tt := range errorTests {
|
||||||
|
|||||||
Reference in New Issue
Block a user