package mathutil
import (
"fmt"
"math"
"math/big"
)
var (
MaxInt128 *big .Int
MinInt128 *big .Int
MaxUint128 *big .Int
)
func init () {
var ok bool
MaxInt128 , ok = big .NewInt (0 ).SetString ("0x7fffffff_ffffffff_ffffffff_ffffffff" , 0 )
if !ok {
panic ("internal error" )
}
MinInt128 = big .NewInt (0 ).Set (MaxInt128 )
MinInt128 .Add (MinInt128 , _1 )
MinInt128 .Neg (MinInt128 )
MaxUint128 , ok = big .NewInt (0 ).SetString ("0xffffffff_ffffffff_ffffffff_ffffffff" , 0 )
if !ok {
panic ("internal error" )
}
}
const (
maxInt128 = 1 <<127 - 1
maxUint128 = 1 <<128 - 1
minInt128 = -maxInt128 - 1
)
type Int128 struct {
Lo int64
Hi int64
}
func (x Int128 ) Add (y Int128 ) (r Int128 , cy bool ) {
r .Lo = x .Lo + y .Lo
r .Hi = x .Hi + y .Hi
if uint64 (r .Lo ) < uint64 (x .Lo ) {
r .Hi ++
}
return r , (r .Cmp (x ) < 0 ) == (y .Sign () >= 0 )
}
func (x Int128 ) BigInt () *big .Int {
r := big .NewInt (x .Hi )
r .Lsh (r , 64 )
lo := big .NewInt (0 )
lo .SetUint64 (uint64 (x .Lo ))
return r .Add (r , lo )
}
func (x Int128 ) Cmp (y Int128 ) int {
if x .Hi > y .Hi {
return 1
}
if x .Hi < y .Hi {
return -1
}
if uint64 (x .Lo ) > uint64 (y .Lo ) {
return 1
}
if uint64 (x .Lo ) < uint64 (y .Lo ) {
return -1
}
return 0
}
func (x Int128 ) Neg () (r Int128 , ok bool ) {
if x == (Int128 {Hi : math .MinInt64 }) {
return x , false
}
x .Lo = ^x .Lo
x .Hi = ^x .Hi
r , _ = x .Add (Int128 {Lo : 1 })
return r , true
}
func (x *Int128 ) SetBigInt (y *big .Int ) (r Int128 , err error ) {
if y .Cmp (MaxInt128 ) > 0 {
return *x , fmt .Errorf ("%T.SetInt: overflow" , x )
}
if y .Cmp (MinInt128 ) < 0 {
return *x , fmt .Errorf ("%T.SetInt: underflow" , x )
}
neg := y .Sign () < 0
var z big .Int
z .Set (y )
if neg {
z .Neg (&z )
}
r .Lo = z .Int64 ()
z .Rsh (&z , 64 )
r .Hi = z .Int64 ()
if neg {
r , _ = r .Neg ()
}
*x = r
return r , nil
}
func (x *Int128 ) SetInt64 (y int64 ) (r Int128 ) {
r .Lo = y
if y >= 0 {
r .Hi = 0
*x = r
return r
}
r .Hi = -1
*x = r
return r
}
func (x *Int128 ) SetUint64 (y uint64 ) (r Int128 ) {
r = Int128 {Lo : int64 (y )}
*x = r
return r
}
func (x Int128 ) Sign () int {
if x .Hi < 0 {
return -1
}
if x .Hi != 0 || x .Lo != 0 {
return 1
}
return 0
}
func (x Int128 ) String () string { return x .BigInt ().String () }
func NewInt128FromInt64 (n int64 ) (r Int128 ) {
r .Lo = n
if n < 0 {
r .Hi = -1
}
return r
}
func NewInt128FromUint64 (n uint64 ) (r Int128 ) { return Int128 {Lo : int64 (n )} }
func NewInt128FromFloat32 (n float32 ) (r Int128 ) {
if n >= minInt128 && n <= maxInt128 {
if n >= math .MinInt64 && n <= math .MaxInt64 {
return NewInt128FromInt64 (int64 (n ))
}
f := big .NewFloat (float64 (n ))
bi , _ := f .Int (nil )
r .SetBigInt (bi )
}
return r
}
func NewInt128FromFloat64 (n float64 ) (r Int128 ) {
if n >= minInt128 && n <= maxInt128 {
if n >= math .MinInt64 && n <= math .MaxInt64 {
return NewInt128FromInt64 (int64 (n ))
}
f := big .NewFloat (n )
bi , _ := f .Int (nil )
r .SetBigInt (bi )
}
return r
}
type Uint128 struct {
Lo uint64
Hi uint64
}
func NewUint128FromInt64 (n int64 ) (r Uint128 ) {
r .Lo = uint64 (n )
if n < 0 {
r .Hi = ^uint64 (0 )
}
return r
}
func NewUint128FromUint64 (n uint64 ) (r Uint128 ) { return Uint128 {Lo : n } }
func NewUint128FromFloat32 (n float32 ) (r Uint128 ) {
if n >= 0 {
if n <= math .MaxUint64 {
return NewUint128FromUint64 (uint64 (n ))
}
f := big .NewFloat (float64 (n ))
bi , _ := f .Int (nil )
r .SetBigInt (bi )
}
return r
}
func NewUint128FromFloat64 (n float64 ) (r Uint128 ) {
if n >= 0 && n <= maxUint128 {
if n <= math .MaxUint64 {
return NewUint128FromUint64 (uint64 (n ))
}
f := big .NewFloat (n )
bi , _ := f .Int (nil )
r .SetBigInt (bi )
}
return r
}
func (x *Uint128 ) SetBigInt (y *big .Int ) (r Uint128 , err error ) {
if y .Sign () < 0 || y .Cmp (MaxUint128 ) > 0 {
return *x , fmt .Errorf ("%T.SetInt: overflow" , x )
}
var z big .Int
z .Set (y )
r .Lo = z .Uint64 ()
z .Rsh (&z , 64 )
r .Hi = z .Uint64 ()
*x = r
return r , nil
}
The pages are generated with Golds v0.3.6 . (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .