mirror of
https://github.com/shopspring/decimal.git
synced 2024-11-22 20:40:48 +01:00
feat: add uint64 surport
This commit is contained in:
parent
cd690d0c9e
commit
f778328e58
2 changed files with 163 additions and 148 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
.git
|
.git
|
||||||
*.swp
|
*.swp
|
||||||
|
.idea/
|
310
decimal.go
310
decimal.go
|
@ -87,6 +87,14 @@ func New(value int64, exp int32) Decimal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFromUint64 returns a new Decimal from a uint64, value * 10 ^ exp
|
||||||
|
func NewFromUint64(value uint64, exp int32) Decimal {
|
||||||
|
return Decimal{
|
||||||
|
value: new(big.Int).SetUint64(value),
|
||||||
|
exp: exp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewFromBigInt returns a new Decimal from a big.Int, value * 10 ^ exp
|
// NewFromBigInt returns a new Decimal from a big.Int, value * 10 ^ exp
|
||||||
func NewFromBigInt(value *big.Int, exp int32) Decimal {
|
func NewFromBigInt(value *big.Int, exp int32) Decimal {
|
||||||
return Decimal{
|
return Decimal{
|
||||||
|
@ -988,6 +996,12 @@ func (d *Decimal) Scan(value interface{}) error {
|
||||||
*d = New(v, 0)
|
*d = New(v, 0)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case uint64:
|
||||||
|
// at least in clickhouse when the value is 0 in db, the data is sent
|
||||||
|
// to us as an uint64 instead of a int64 ...
|
||||||
|
*d = NewFromUint64(v, 0)
|
||||||
|
return nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// default is trying to interpret value stored as string
|
// default is trying to interpret value stored as string
|
||||||
str, err := unquoteIfQuoted(v)
|
str, err := unquoteIfQuoted(v)
|
||||||
|
@ -1261,174 +1275,174 @@ func (d Decimal) satan() Decimal {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sin coefficients
|
// sin coefficients
|
||||||
var _sin = [...]Decimal{
|
var _sin = [...]Decimal{
|
||||||
NewFromFloat(1.58962301576546568060E-10), // 0x3de5d8fd1fd19ccd
|
NewFromFloat(1.58962301576546568060E-10), // 0x3de5d8fd1fd19ccd
|
||||||
NewFromFloat(-2.50507477628578072866E-8), // 0xbe5ae5e5a9291f5d
|
NewFromFloat(-2.50507477628578072866E-8), // 0xbe5ae5e5a9291f5d
|
||||||
NewFromFloat(2.75573136213857245213E-6), // 0x3ec71de3567d48a1
|
NewFromFloat(2.75573136213857245213E-6), // 0x3ec71de3567d48a1
|
||||||
NewFromFloat(-1.98412698295895385996E-4), // 0xbf2a01a019bfdf03
|
NewFromFloat(-1.98412698295895385996E-4), // 0xbf2a01a019bfdf03
|
||||||
NewFromFloat(8.33333333332211858878E-3), // 0x3f8111111110f7d0
|
NewFromFloat(8.33333333332211858878E-3), // 0x3f8111111110f7d0
|
||||||
NewFromFloat(-1.66666666666666307295E-1), // 0xbfc5555555555548
|
NewFromFloat(-1.66666666666666307295E-1), // 0xbfc5555555555548
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sin returns the sine of the radian argument x.
|
// Sin returns the sine of the radian argument x.
|
||||||
func (d Decimal) Sin() Decimal {
|
func (d Decimal) Sin() Decimal {
|
||||||
PI4A := NewFromFloat(7.85398125648498535156E-1) // 0x3fe921fb40000000, Pi/4 split into three parts
|
PI4A := NewFromFloat(7.85398125648498535156E-1) // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||||
PI4B := NewFromFloat(3.77489470793079817668E-8) // 0x3e64442d00000000,
|
PI4B := NewFromFloat(3.77489470793079817668E-8) // 0x3e64442d00000000,
|
||||||
PI4C := NewFromFloat(2.69515142907905952645E-15) // 0x3ce8469898cc5170,
|
PI4C := NewFromFloat(2.69515142907905952645E-15) // 0x3ce8469898cc5170,
|
||||||
M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
|
M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
|
||||||
|
|
||||||
if d.Equal(NewFromFloat(0.0)) {
|
if d.Equal(NewFromFloat(0.0)) {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
// make argument positive but save the sign
|
// make argument positive but save the sign
|
||||||
sign := false
|
sign := false
|
||||||
if d.LessThan(NewFromFloat(0.0)) {
|
if d.LessThan(NewFromFloat(0.0)) {
|
||||||
d = d.Neg()
|
d = d.Neg()
|
||||||
sign = true
|
sign = true
|
||||||
}
|
}
|
||||||
|
|
||||||
j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
|
j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||||
y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
|
y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
|
||||||
|
|
||||||
// map zeros to origin
|
// map zeros to origin
|
||||||
if j&1 == 1 {
|
if j&1 == 1 {
|
||||||
j++
|
j++
|
||||||
y = y.Add(NewFromFloat(1.0))
|
y = y.Add(NewFromFloat(1.0))
|
||||||
}
|
}
|
||||||
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
||||||
// reflect in x axis
|
// reflect in x axis
|
||||||
if j > 3 {
|
if j > 3 {
|
||||||
sign = !sign
|
sign = !sign
|
||||||
j -= 4
|
j -= 4
|
||||||
}
|
}
|
||||||
z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
|
z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
|
||||||
zz := z.Mul(z)
|
zz := z.Mul(z)
|
||||||
|
|
||||||
if j == 1 || j == 2 {
|
if j == 1 || j == 2 {
|
||||||
w := zz.Mul(zz).Mul(_cos[0].Mul(zz).Add(_cos[1]).Mul(zz).Add(_cos[2]).Mul(zz).Add(_cos[3]).Mul(zz).Add(_cos[4]).Mul(zz).Add(_cos[5]))
|
w := zz.Mul(zz).Mul(_cos[0].Mul(zz).Add(_cos[1]).Mul(zz).Add(_cos[2]).Mul(zz).Add(_cos[3]).Mul(zz).Add(_cos[4]).Mul(zz).Add(_cos[5]))
|
||||||
y = NewFromFloat(1.0).Sub(NewFromFloat(0.5).Mul(zz)).Add(w)
|
y = NewFromFloat(1.0).Sub(NewFromFloat(0.5).Mul(zz)).Add(w)
|
||||||
} else {
|
} else {
|
||||||
y = z.Add(z.Mul(zz).Mul(_sin[0].Mul(zz).Add(_sin[1]).Mul(zz).Add(_sin[2]).Mul(zz).Add(_sin[3]).Mul(zz).Add(_sin[4]).Mul(zz).Add(_sin[5])))
|
y = z.Add(z.Mul(zz).Mul(_sin[0].Mul(zz).Add(_sin[1]).Mul(zz).Add(_sin[2]).Mul(zz).Add(_sin[3]).Mul(zz).Add(_sin[4]).Mul(zz).Add(_sin[5])))
|
||||||
}
|
}
|
||||||
if sign {
|
if sign {
|
||||||
y = y.Neg()
|
y = y.Neg()
|
||||||
}
|
}
|
||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
|
|
||||||
// cos coefficients
|
// cos coefficients
|
||||||
var _cos = [...]Decimal{
|
var _cos = [...]Decimal{
|
||||||
NewFromFloat(-1.13585365213876817300E-11), // 0xbda8fa49a0861a9b
|
NewFromFloat(-1.13585365213876817300E-11), // 0xbda8fa49a0861a9b
|
||||||
NewFromFloat(2.08757008419747316778E-9), // 0x3e21ee9d7b4e3f05
|
NewFromFloat(2.08757008419747316778E-9), // 0x3e21ee9d7b4e3f05
|
||||||
NewFromFloat(-2.75573141792967388112E-7), // 0xbe927e4f7eac4bc6
|
NewFromFloat(-2.75573141792967388112E-7), // 0xbe927e4f7eac4bc6
|
||||||
NewFromFloat(2.48015872888517045348E-5), // 0x3efa01a019c844f5
|
NewFromFloat(2.48015872888517045348E-5), // 0x3efa01a019c844f5
|
||||||
NewFromFloat(-1.38888888888730564116E-3), // 0xbf56c16c16c14f91
|
NewFromFloat(-1.38888888888730564116E-3), // 0xbf56c16c16c14f91
|
||||||
NewFromFloat(4.16666666666665929218E-2), // 0x3fa555555555554b
|
NewFromFloat(4.16666666666665929218E-2), // 0x3fa555555555554b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cos returns the cosine of the radian argument x.
|
// Cos returns the cosine of the radian argument x.
|
||||||
func (d Decimal) Cos() Decimal {
|
func (d Decimal) Cos() Decimal {
|
||||||
|
|
||||||
PI4A := NewFromFloat(7.85398125648498535156E-1) // 0x3fe921fb40000000, Pi/4 split into three parts
|
PI4A := NewFromFloat(7.85398125648498535156E-1) // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||||
PI4B := NewFromFloat(3.77489470793079817668E-8) // 0x3e64442d00000000,
|
PI4B := NewFromFloat(3.77489470793079817668E-8) // 0x3e64442d00000000,
|
||||||
PI4C := NewFromFloat(2.69515142907905952645E-15) // 0x3ce8469898cc5170,
|
PI4C := NewFromFloat(2.69515142907905952645E-15) // 0x3ce8469898cc5170,
|
||||||
M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
|
M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
|
||||||
|
|
||||||
// make argument positive
|
// make argument positive
|
||||||
sign := false
|
sign := false
|
||||||
if d.LessThan(NewFromFloat(0.0)) {
|
if d.LessThan(NewFromFloat(0.0)) {
|
||||||
d = d.Neg()
|
d = d.Neg()
|
||||||
}
|
}
|
||||||
|
|
||||||
j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
|
j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||||
y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
|
y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
|
||||||
|
|
||||||
// map zeros to origin
|
// map zeros to origin
|
||||||
if j&1 == 1 {
|
if j&1 == 1 {
|
||||||
j++
|
j++
|
||||||
y = y.Add(NewFromFloat(1.0))
|
y = y.Add(NewFromFloat(1.0))
|
||||||
}
|
}
|
||||||
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
||||||
// reflect in x axis
|
// reflect in x axis
|
||||||
if j > 3 {
|
if j > 3 {
|
||||||
sign = !sign
|
sign = !sign
|
||||||
j -= 4
|
j -= 4
|
||||||
}
|
}
|
||||||
if j > 1 {
|
if j > 1 {
|
||||||
sign = !sign
|
sign = !sign
|
||||||
}
|
}
|
||||||
|
|
||||||
z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
|
z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
|
||||||
zz := z.Mul(z)
|
zz := z.Mul(z)
|
||||||
|
|
||||||
if j == 1 || j == 2 {
|
if j == 1 || j == 2 {
|
||||||
y = z.Add(z.Mul(zz).Mul(_sin[0].Mul(zz).Add(_sin[1]).Mul(zz).Add(_sin[2]).Mul(zz).Add(_sin[3]).Mul(zz).Add(_sin[4]).Mul(zz).Add(_sin[5])))
|
y = z.Add(z.Mul(zz).Mul(_sin[0].Mul(zz).Add(_sin[1]).Mul(zz).Add(_sin[2]).Mul(zz).Add(_sin[3]).Mul(zz).Add(_sin[4]).Mul(zz).Add(_sin[5])))
|
||||||
} else {
|
} else {
|
||||||
w := zz.Mul(zz).Mul(_cos[0].Mul(zz).Add(_cos[1]).Mul(zz).Add(_cos[2]).Mul(zz).Add(_cos[3]).Mul(zz).Add(_cos[4]).Mul(zz).Add(_cos[5]))
|
w := zz.Mul(zz).Mul(_cos[0].Mul(zz).Add(_cos[1]).Mul(zz).Add(_cos[2]).Mul(zz).Add(_cos[3]).Mul(zz).Add(_cos[4]).Mul(zz).Add(_cos[5]))
|
||||||
y = NewFromFloat(1.0).Sub(NewFromFloat(0.5).Mul(zz)).Add(w)
|
y = NewFromFloat(1.0).Sub(NewFromFloat(0.5).Mul(zz)).Add(w)
|
||||||
}
|
}
|
||||||
if sign {
|
if sign {
|
||||||
y = y.Neg()
|
y = y.Neg()
|
||||||
}
|
}
|
||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
|
|
||||||
var _tanP = [...]Decimal{
|
var _tanP = [...]Decimal{
|
||||||
NewFromFloat(-1.30936939181383777646E+4), // 0xc0c992d8d24f3f38
|
NewFromFloat(-1.30936939181383777646E+4), // 0xc0c992d8d24f3f38
|
||||||
NewFromFloat(1.15351664838587416140E+6), // 0x413199eca5fc9ddd
|
NewFromFloat(1.15351664838587416140E+6), // 0x413199eca5fc9ddd
|
||||||
NewFromFloat(-1.79565251976484877988E+7), // 0xc1711fead3299176
|
NewFromFloat(-1.79565251976484877988E+7), // 0xc1711fead3299176
|
||||||
}
|
}
|
||||||
var _tanQ = [...]Decimal{
|
var _tanQ = [...]Decimal{
|
||||||
NewFromFloat(1.00000000000000000000E+0),
|
NewFromFloat(1.00000000000000000000E+0),
|
||||||
NewFromFloat(1.36812963470692954678E+4), //0x40cab8a5eeb36572
|
NewFromFloat(1.36812963470692954678E+4), //0x40cab8a5eeb36572
|
||||||
NewFromFloat(-1.32089234440210967447E+6), //0xc13427bc582abc96
|
NewFromFloat(-1.32089234440210967447E+6), //0xc13427bc582abc96
|
||||||
NewFromFloat(2.50083801823357915839E+7), //0x4177d98fc2ead8ef
|
NewFromFloat(2.50083801823357915839E+7), //0x4177d98fc2ead8ef
|
||||||
NewFromFloat(-5.38695755929454629881E+7), //0xc189afe03cbe5a31
|
NewFromFloat(-5.38695755929454629881E+7), //0xc189afe03cbe5a31
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tan returns the tangent of the radian argument x.
|
// Tan returns the tangent of the radian argument x.
|
||||||
func (d Decimal) Tan() Decimal {
|
func (d Decimal) Tan() Decimal {
|
||||||
|
|
||||||
PI4A := NewFromFloat(7.85398125648498535156E-1) // 0x3fe921fb40000000, Pi/4 split into three parts
|
PI4A := NewFromFloat(7.85398125648498535156E-1) // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||||
PI4B := NewFromFloat(3.77489470793079817668E-8) // 0x3e64442d00000000,
|
PI4B := NewFromFloat(3.77489470793079817668E-8) // 0x3e64442d00000000,
|
||||||
PI4C := NewFromFloat(2.69515142907905952645E-15) // 0x3ce8469898cc5170,
|
PI4C := NewFromFloat(2.69515142907905952645E-15) // 0x3ce8469898cc5170,
|
||||||
M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
|
M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
|
||||||
|
|
||||||
if d.Equal(NewFromFloat(0.0)) {
|
if d.Equal(NewFromFloat(0.0)) {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// make argument positive but save the sign
|
// make argument positive but save the sign
|
||||||
sign := false
|
sign := false
|
||||||
if d.LessThan(NewFromFloat(0.0)) {
|
if d.LessThan(NewFromFloat(0.0)) {
|
||||||
d = d.Neg()
|
d = d.Neg()
|
||||||
sign = true
|
sign = true
|
||||||
}
|
}
|
||||||
|
|
||||||
j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
|
j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||||
y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
|
y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
|
||||||
|
|
||||||
// map zeros to origin
|
// map zeros to origin
|
||||||
if j&1 == 1 {
|
if j&1 == 1 {
|
||||||
j++
|
j++
|
||||||
y = y.Add(NewFromFloat(1.0))
|
y = y.Add(NewFromFloat(1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
|
z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
|
||||||
zz := z.Mul(z)
|
zz := z.Mul(z)
|
||||||
|
|
||||||
if zz.GreaterThan(NewFromFloat(1e-14)) {
|
if zz.GreaterThan(NewFromFloat(1e-14)) {
|
||||||
w := zz.Mul(_tanP[0].Mul(zz).Add(_tanP[1]).Mul(zz).Add(_tanP[2]))
|
w := zz.Mul(_tanP[0].Mul(zz).Add(_tanP[1]).Mul(zz).Add(_tanP[2]))
|
||||||
x := zz.Add(_tanQ[1]).Mul(zz).Add(_tanQ[2]).Mul(zz).Add(_tanQ[3]).Mul(zz).Add(_tanQ[4])
|
x := zz.Add(_tanQ[1]).Mul(zz).Add(_tanQ[2]).Mul(zz).Add(_tanQ[3]).Mul(zz).Add(_tanQ[4])
|
||||||
y = z.Add(z.Mul(w.Div(x)))
|
y = z.Add(z.Mul(w.Div(x)))
|
||||||
} else {
|
} else {
|
||||||
y = z
|
y = z
|
||||||
}
|
}
|
||||||
if j&2 == 2 {
|
if j&2 == 2 {
|
||||||
y = NewFromFloat(-1.0).Div(y)
|
y = NewFromFloat(-1.0).Div(y)
|
||||||
}
|
}
|
||||||
if sign {
|
if sign {
|
||||||
y = y.Neg()
|
y = y.Neg()
|
||||||
}
|
}
|
||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue