gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

uint128.go (10108B)


      1 package uint128 // import "lukechampine.com/uint128"
      2 
      3 import (
      4 	"encoding/binary"
      5 	"errors"
      6 	"fmt"
      7 	"math"
      8 	"math/big"
      9 	"math/bits"
     10 )
     11 
     12 // Zero is a zero-valued uint128.
     13 var Zero Uint128
     14 
     15 // Max is the largest possible uint128 value.
     16 var Max = New(math.MaxUint64, math.MaxUint64)
     17 
     18 // A Uint128 is an unsigned 128-bit number.
     19 type Uint128 struct {
     20 	Lo, Hi uint64
     21 }
     22 
     23 // IsZero returns true if u == 0.
     24 func (u Uint128) IsZero() bool {
     25 	// NOTE: we do not compare against Zero, because that is a global variable
     26 	// that could be modified.
     27 	return u == Uint128{}
     28 }
     29 
     30 // Equals returns true if u == v.
     31 //
     32 // Uint128 values can be compared directly with ==, but use of the Equals method
     33 // is preferred for consistency.
     34 func (u Uint128) Equals(v Uint128) bool {
     35 	return u == v
     36 }
     37 
     38 // Equals64 returns true if u == v.
     39 func (u Uint128) Equals64(v uint64) bool {
     40 	return u.Lo == v && u.Hi == 0
     41 }
     42 
     43 // Cmp compares u and v and returns:
     44 //
     45 //   -1 if u <  v
     46 //    0 if u == v
     47 //   +1 if u >  v
     48 //
     49 func (u Uint128) Cmp(v Uint128) int {
     50 	if u == v {
     51 		return 0
     52 	} else if u.Hi < v.Hi || (u.Hi == v.Hi && u.Lo < v.Lo) {
     53 		return -1
     54 	} else {
     55 		return 1
     56 	}
     57 }
     58 
     59 // Cmp64 compares u and v and returns:
     60 //
     61 //   -1 if u <  v
     62 //    0 if u == v
     63 //   +1 if u >  v
     64 //
     65 func (u Uint128) Cmp64(v uint64) int {
     66 	if u.Hi == 0 && u.Lo == v {
     67 		return 0
     68 	} else if u.Hi == 0 && u.Lo < v {
     69 		return -1
     70 	} else {
     71 		return 1
     72 	}
     73 }
     74 
     75 // And returns u&v.
     76 func (u Uint128) And(v Uint128) Uint128 {
     77 	return Uint128{u.Lo & v.Lo, u.Hi & v.Hi}
     78 }
     79 
     80 // And64 returns u&v.
     81 func (u Uint128) And64(v uint64) Uint128 {
     82 	return Uint128{u.Lo & v, u.Hi & 0}
     83 }
     84 
     85 // Or returns u|v.
     86 func (u Uint128) Or(v Uint128) Uint128 {
     87 	return Uint128{u.Lo | v.Lo, u.Hi | v.Hi}
     88 }
     89 
     90 // Or64 returns u|v.
     91 func (u Uint128) Or64(v uint64) Uint128 {
     92 	return Uint128{u.Lo | v, u.Hi | 0}
     93 }
     94 
     95 // Xor returns u^v.
     96 func (u Uint128) Xor(v Uint128) Uint128 {
     97 	return Uint128{u.Lo ^ v.Lo, u.Hi ^ v.Hi}
     98 }
     99 
    100 // Xor64 returns u^v.
    101 func (u Uint128) Xor64(v uint64) Uint128 {
    102 	return Uint128{u.Lo ^ v, u.Hi ^ 0}
    103 }
    104 
    105 // Add returns u+v.
    106 func (u Uint128) Add(v Uint128) Uint128 {
    107 	lo, carry := bits.Add64(u.Lo, v.Lo, 0)
    108 	hi, carry := bits.Add64(u.Hi, v.Hi, carry)
    109 	if carry != 0 {
    110 		panic("overflow")
    111 	}
    112 	return Uint128{lo, hi}
    113 }
    114 
    115 // AddWrap returns u+v with wraparound semantics; for example,
    116 // Max.AddWrap(From64(1)) == Zero.
    117 func (u Uint128) AddWrap(v Uint128) Uint128 {
    118 	lo, carry := bits.Add64(u.Lo, v.Lo, 0)
    119 	hi, _ := bits.Add64(u.Hi, v.Hi, carry)
    120 	return Uint128{lo, hi}
    121 }
    122 
    123 // Add64 returns u+v.
    124 func (u Uint128) Add64(v uint64) Uint128 {
    125 	lo, carry := bits.Add64(u.Lo, v, 0)
    126 	hi, carry := bits.Add64(u.Hi, 0, carry)
    127 	if carry != 0 {
    128 		panic("overflow")
    129 	}
    130 	return Uint128{lo, hi}
    131 }
    132 
    133 // AddWrap64 returns u+v with wraparound semantics; for example,
    134 // Max.AddWrap64(1) == Zero.
    135 func (u Uint128) AddWrap64(v uint64) Uint128 {
    136 	lo, carry := bits.Add64(u.Lo, v, 0)
    137 	hi := u.Hi + carry
    138 	return Uint128{lo, hi}
    139 }
    140 
    141 // Sub returns u-v.
    142 func (u Uint128) Sub(v Uint128) Uint128 {
    143 	lo, borrow := bits.Sub64(u.Lo, v.Lo, 0)
    144 	hi, borrow := bits.Sub64(u.Hi, v.Hi, borrow)
    145 	if borrow != 0 {
    146 		panic("underflow")
    147 	}
    148 	return Uint128{lo, hi}
    149 }
    150 
    151 // SubWrap returns u-v with wraparound semantics; for example,
    152 // Zero.SubWrap(From64(1)) == Max.
    153 func (u Uint128) SubWrap(v Uint128) Uint128 {
    154 	lo, borrow := bits.Sub64(u.Lo, v.Lo, 0)
    155 	hi, _ := bits.Sub64(u.Hi, v.Hi, borrow)
    156 	return Uint128{lo, hi}
    157 }
    158 
    159 // Sub64 returns u-v.
    160 func (u Uint128) Sub64(v uint64) Uint128 {
    161 	lo, borrow := bits.Sub64(u.Lo, v, 0)
    162 	hi, borrow := bits.Sub64(u.Hi, 0, borrow)
    163 	if borrow != 0 {
    164 		panic("underflow")
    165 	}
    166 	return Uint128{lo, hi}
    167 }
    168 
    169 // SubWrap64 returns u-v with wraparound semantics; for example,
    170 // Zero.SubWrap64(1) == Max.
    171 func (u Uint128) SubWrap64(v uint64) Uint128 {
    172 	lo, borrow := bits.Sub64(u.Lo, v, 0)
    173 	hi := u.Hi - borrow
    174 	return Uint128{lo, hi}
    175 }
    176 
    177 // Mul returns u*v, panicking on overflow.
    178 func (u Uint128) Mul(v Uint128) Uint128 {
    179 	hi, lo := bits.Mul64(u.Lo, v.Lo)
    180 	p0, p1 := bits.Mul64(u.Hi, v.Lo)
    181 	p2, p3 := bits.Mul64(u.Lo, v.Hi)
    182 	hi, c0 := bits.Add64(hi, p1, 0)
    183 	hi, c1 := bits.Add64(hi, p3, c0)
    184 	if (u.Hi != 0 && v.Hi != 0) || p0 != 0 || p2 != 0 || c1 != 0 {
    185 		panic("overflow")
    186 	}
    187 	return Uint128{lo, hi}
    188 }
    189 
    190 // MulWrap returns u*v with wraparound semantics; for example,
    191 // Max.MulWrap(Max) == 1.
    192 func (u Uint128) MulWrap(v Uint128) Uint128 {
    193 	hi, lo := bits.Mul64(u.Lo, v.Lo)
    194 	hi += u.Hi*v.Lo + u.Lo*v.Hi
    195 	return Uint128{lo, hi}
    196 }
    197 
    198 // Mul64 returns u*v, panicking on overflow.
    199 func (u Uint128) Mul64(v uint64) Uint128 {
    200 	hi, lo := bits.Mul64(u.Lo, v)
    201 	p0, p1 := bits.Mul64(u.Hi, v)
    202 	hi, c0 := bits.Add64(hi, p1, 0)
    203 	if p0 != 0 || c0 != 0 {
    204 		panic("overflow")
    205 	}
    206 	return Uint128{lo, hi}
    207 }
    208 
    209 // MulWrap64 returns u*v with wraparound semantics; for example,
    210 // Max.MulWrap64(2) == Max.Sub64(1).
    211 func (u Uint128) MulWrap64(v uint64) Uint128 {
    212 	hi, lo := bits.Mul64(u.Lo, v)
    213 	hi += u.Hi * v
    214 	return Uint128{lo, hi}
    215 }
    216 
    217 // Div returns u/v.
    218 func (u Uint128) Div(v Uint128) Uint128 {
    219 	q, _ := u.QuoRem(v)
    220 	return q
    221 }
    222 
    223 // Div64 returns u/v.
    224 func (u Uint128) Div64(v uint64) Uint128 {
    225 	q, _ := u.QuoRem64(v)
    226 	return q
    227 }
    228 
    229 // QuoRem returns q = u/v and r = u%v.
    230 func (u Uint128) QuoRem(v Uint128) (q, r Uint128) {
    231 	if v.Hi == 0 {
    232 		var r64 uint64
    233 		q, r64 = u.QuoRem64(v.Lo)
    234 		r = From64(r64)
    235 	} else {
    236 		// generate a "trial quotient," guaranteed to be within 1 of the actual
    237 		// quotient, then adjust.
    238 		n := uint(bits.LeadingZeros64(v.Hi))
    239 		v1 := v.Lsh(n)
    240 		u1 := u.Rsh(1)
    241 		tq, _ := bits.Div64(u1.Hi, u1.Lo, v1.Hi)
    242 		tq >>= 63 - n
    243 		if tq != 0 {
    244 			tq--
    245 		}
    246 		q = From64(tq)
    247 		// calculate remainder using trial quotient, then adjust if remainder is
    248 		// greater than divisor
    249 		r = u.Sub(v.Mul64(tq))
    250 		if r.Cmp(v) >= 0 {
    251 			q = q.Add64(1)
    252 			r = r.Sub(v)
    253 		}
    254 	}
    255 	return
    256 }
    257 
    258 // QuoRem64 returns q = u/v and r = u%v.
    259 func (u Uint128) QuoRem64(v uint64) (q Uint128, r uint64) {
    260 	if u.Hi < v {
    261 		q.Lo, r = bits.Div64(u.Hi, u.Lo, v)
    262 	} else {
    263 		q.Hi, r = bits.Div64(0, u.Hi, v)
    264 		q.Lo, r = bits.Div64(r, u.Lo, v)
    265 	}
    266 	return
    267 }
    268 
    269 // Mod returns r = u%v.
    270 func (u Uint128) Mod(v Uint128) (r Uint128) {
    271 	_, r = u.QuoRem(v)
    272 	return
    273 }
    274 
    275 // Mod64 returns r = u%v.
    276 func (u Uint128) Mod64(v uint64) (r uint64) {
    277 	_, r = u.QuoRem64(v)
    278 	return
    279 }
    280 
    281 // Lsh returns u<<n.
    282 func (u Uint128) Lsh(n uint) (s Uint128) {
    283 	if n > 64 {
    284 		s.Lo = 0
    285 		s.Hi = u.Lo << (n - 64)
    286 	} else {
    287 		s.Lo = u.Lo << n
    288 		s.Hi = u.Hi<<n | u.Lo>>(64-n)
    289 	}
    290 	return
    291 }
    292 
    293 // Rsh returns u>>n.
    294 func (u Uint128) Rsh(n uint) (s Uint128) {
    295 	if n > 64 {
    296 		s.Lo = u.Hi >> (n - 64)
    297 		s.Hi = 0
    298 	} else {
    299 		s.Lo = u.Lo>>n | u.Hi<<(64-n)
    300 		s.Hi = u.Hi >> n
    301 	}
    302 	return
    303 }
    304 
    305 // LeadingZeros returns the number of leading zero bits in u; the result is 128
    306 // for u == 0.
    307 func (u Uint128) LeadingZeros() int {
    308 	if u.Hi > 0 {
    309 		return bits.LeadingZeros64(u.Hi)
    310 	}
    311 	return 64 + bits.LeadingZeros64(u.Lo)
    312 }
    313 
    314 // TrailingZeros returns the number of trailing zero bits in u; the result is
    315 // 128 for u == 0.
    316 func (u Uint128) TrailingZeros() int {
    317 	if u.Lo > 0 {
    318 		return bits.TrailingZeros64(u.Lo)
    319 	}
    320 	return 64 + bits.TrailingZeros64(u.Hi)
    321 }
    322 
    323 // OnesCount returns the number of one bits ("population count") in u.
    324 func (u Uint128) OnesCount() int {
    325 	return bits.OnesCount64(u.Hi) + bits.OnesCount64(u.Lo)
    326 }
    327 
    328 // RotateLeft returns the value of u rotated left by (k mod 128) bits.
    329 func (u Uint128) RotateLeft(k int) Uint128 {
    330 	const n = 128
    331 	s := uint(k) & (n - 1)
    332 	return u.Lsh(s).Or(u.Rsh(n - s))
    333 }
    334 
    335 // RotateRight returns the value of u rotated left by (k mod 128) bits.
    336 func (u Uint128) RotateRight(k int) Uint128 {
    337 	return u.RotateLeft(-k)
    338 }
    339 
    340 // Reverse returns the value of u with its bits in reversed order.
    341 func (u Uint128) Reverse() Uint128 {
    342 	return Uint128{bits.Reverse64(u.Hi), bits.Reverse64(u.Lo)}
    343 }
    344 
    345 // ReverseBytes returns the value of u with its bytes in reversed order.
    346 func (u Uint128) ReverseBytes() Uint128 {
    347 	return Uint128{bits.ReverseBytes64(u.Hi), bits.ReverseBytes64(u.Lo)}
    348 }
    349 
    350 // Len returns the minimum number of bits required to represent u; the result is
    351 // 0 for u == 0.
    352 func (u Uint128) Len() int {
    353 	return 128 - u.LeadingZeros()
    354 }
    355 
    356 // String returns the base-10 representation of u as a string.
    357 func (u Uint128) String() string {
    358 	if u.IsZero() {
    359 		return "0"
    360 	}
    361 	buf := []byte("0000000000000000000000000000000000000000") // log10(2^128) < 40
    362 	for i := len(buf); ; i -= 19 {
    363 		q, r := u.QuoRem64(1e19) // largest power of 10 that fits in a uint64
    364 		var n int
    365 		for ; r != 0; r /= 10 {
    366 			n++
    367 			buf[i-n] += byte(r % 10)
    368 		}
    369 		if q.IsZero() {
    370 			return string(buf[i-n:])
    371 		}
    372 		u = q
    373 	}
    374 }
    375 
    376 // PutBytes stores u in b in little-endian order. It panics if len(b) < 16.
    377 func (u Uint128) PutBytes(b []byte) {
    378 	binary.LittleEndian.PutUint64(b[:8], u.Lo)
    379 	binary.LittleEndian.PutUint64(b[8:], u.Hi)
    380 }
    381 
    382 // Big returns u as a *big.Int.
    383 func (u Uint128) Big() *big.Int {
    384 	i := new(big.Int).SetUint64(u.Hi)
    385 	i = i.Lsh(i, 64)
    386 	i = i.Xor(i, new(big.Int).SetUint64(u.Lo))
    387 	return i
    388 }
    389 
    390 // Scan implements fmt.Scanner.
    391 func (u *Uint128) Scan(s fmt.ScanState, ch rune) error {
    392 	i := new(big.Int)
    393 	if err := i.Scan(s, ch); err != nil {
    394 		return err
    395 	} else if i.Sign() < 0 {
    396 		return errors.New("value cannot be negative")
    397 	} else if i.BitLen() > 128 {
    398 		return errors.New("value overflows Uint128")
    399 	}
    400 	u.Lo = i.Uint64()
    401 	u.Hi = i.Rsh(i, 64).Uint64()
    402 	return nil
    403 }
    404 
    405 // New returns the Uint128 value (lo,hi).
    406 func New(lo, hi uint64) Uint128 {
    407 	return Uint128{lo, hi}
    408 }
    409 
    410 // From64 converts v to a Uint128 value.
    411 func From64(v uint64) Uint128 {
    412 	return New(v, 0)
    413 }
    414 
    415 // FromBytes converts b to a Uint128 value.
    416 func FromBytes(b []byte) Uint128 {
    417 	return New(
    418 		binary.LittleEndian.Uint64(b[:8]),
    419 		binary.LittleEndian.Uint64(b[8:]),
    420 	)
    421 }
    422 
    423 // FromBig converts i to a Uint128 value. It panics if i is negative or
    424 // overflows 128 bits.
    425 func FromBig(i *big.Int) (u Uint128) {
    426 	if i.Sign() < 0 {
    427 		panic("value cannot be negative")
    428 	} else if i.BitLen() > 128 {
    429 		panic("value overflows Uint128")
    430 	}
    431 	u.Lo = i.Uint64()
    432 	u.Hi = i.Rsh(i, 64).Uint64()
    433 	return u
    434 }
    435 
    436 // FromString parses s as a Uint128 value.
    437 func FromString(s string) (u Uint128, err error) {
    438 	_, err = fmt.Sscan(s, &u)
    439 	return
    440 }