// uint256: Fixed size 256-bit math library // Copyright 2018-2020 uint256 Authors // SPDX-License-Identifier: BSD-3-Clause // Package math provides integer math utilities. package uint256 import ( "encoding/binary" "math" "math/bits" ) // Int is represented as an array of 4 uint64, in little-endian order, // so that Int[3] is the most significant, and Int[0] is the least significant type Int [4]uint64 // NewInt returns a new initialized Int. func NewInt(val uint64) *Int { z := &Int{} z.SetUint64(val) return z } // SetBytes interprets buf as the bytes of a big-endian unsigned // integer, sets z to that value, and returns z. // If buf is larger than 32 bytes, the last 32 bytes is used. This operation // is semantically equivalent to `FromBig(new(big.Int).SetBytes(buf))` func (z *Int) SetBytes(buf []byte) *Int { switch l := len(buf); l { case 0: z.Clear() case 1: z.SetBytes1(buf) case 2: z.SetBytes2(buf) case 3: z.SetBytes3(buf) case 4: z.SetBytes4(buf) case 5: z.SetBytes5(buf) case 6: z.SetBytes6(buf) case 7: z.SetBytes7(buf) case 8: z.SetBytes8(buf) case 9: z.SetBytes9(buf) case 10: z.SetBytes10(buf) case 11: z.SetBytes11(buf) case 12: z.SetBytes12(buf) case 13: z.SetBytes13(buf) case 14: z.SetBytes14(buf) case 15: z.SetBytes15(buf) case 16: z.SetBytes16(buf) case 17: z.SetBytes17(buf) case 18: z.SetBytes18(buf) case 19: z.SetBytes19(buf) case 20: z.SetBytes20(buf) case 21: z.SetBytes21(buf) case 22: z.SetBytes22(buf) case 23: z.SetBytes23(buf) case 24: z.SetBytes24(buf) case 25: z.SetBytes25(buf) case 26: z.SetBytes26(buf) case 27: z.SetBytes27(buf) case 28: z.SetBytes28(buf) case 29: z.SetBytes29(buf) case 30: z.SetBytes30(buf) case 31: z.SetBytes31(buf) default: z.SetBytes32(buf[l-32:]) } return z } // Bytes32 returns the value of z as a 32-byte big-endian array. func (z *Int) Bytes32() [32]byte { // The PutUint64()s are inlined and we get 4x (load, bswap, store) instructions. var b [32]byte binary.BigEndian.PutUint64(b[0:8], z[3]) binary.BigEndian.PutUint64(b[8:16], z[2]) binary.BigEndian.PutUint64(b[16:24], z[1]) binary.BigEndian.PutUint64(b[24:32], z[0]) return b } // Bytes20 returns the value of z as a 20-byte big-endian array. func (z *Int) Bytes20() [20]byte { var b [20]byte // The PutUint*()s are inlined and we get 3x (load, bswap, store) instructions. binary.BigEndian.PutUint32(b[0:4], uint32(z[2])) binary.BigEndian.PutUint64(b[4:12], z[1]) binary.BigEndian.PutUint64(b[12:20], z[0]) return b } // Bytes returns the value of z as a big-endian byte slice. func (z *Int) Bytes() []byte { b := z.Bytes32() return b[32-z.ByteLen():] } // WriteToSlice writes the content of z into the given byteslice. // If dest is larger than 32 bytes, z will fill the first parts, and leave // the end untouched. // OBS! If dest is smaller than 32 bytes, only the end parts of z will be used // for filling the array, making it useful for filling an Address object func (z *Int) WriteToSlice(dest []byte) { // ensure 32 bytes // A too large buffer. Fill last 32 bytes end := len(dest) - 1 if end > 31 { end = 31 } for i := 0; i <= end; i++ { dest[end-i] = byte(z[i/8] >> uint64(8*(i%8))) } } // WriteToArray32 writes all 32 bytes of z to the destination array, including zero-bytes func (z *Int) WriteToArray32(dest *[32]byte) { for i := 0; i < 32; i++ { dest[31-i] = byte(z[i/8] >> uint64(8*(i%8))) } } // WriteToArray20 writes the last 20 bytes of z to the destination array, including zero-bytes func (z *Int) WriteToArray20(dest *[20]byte) { for i := 0; i < 20; i++ { dest[19-i] = byte(z[i/8] >> uint64(8*(i%8))) } } // Uint64 returns the lower 64-bits of z func (z *Int) Uint64() uint64 { return z[0] } // Uint64WithOverflow returns the lower 64-bits of z and bool whether overflow occurred func (z *Int) Uint64WithOverflow() (uint64, bool) { return z[0], (z[1] | z[2] | z[3]) != 0 } // Clone creates a new Int identical to z func (z *Int) Clone() *Int { return &Int{z[0], z[1], z[2], z[3]} } // Add sets z to the sum x+y func (z *Int) Add(x, y *Int) *Int { var carry uint64 z[0], carry = bits.Add64(x[0], y[0], 0) z[1], carry = bits.Add64(x[1], y[1], carry) z[2], carry = bits.Add64(x[2], y[2], carry) z[3], _ = bits.Add64(x[3], y[3], carry) return z } // AddOverflow sets z to the sum x+y, and returns z and whether overflow occurred func (z *Int) AddOverflow(x, y *Int) (*Int, bool) { var carry uint64 z[0], carry = bits.Add64(x[0], y[0], 0) z[1], carry = bits.Add64(x[1], y[1], carry) z[2], carry = bits.Add64(x[2], y[2], carry) z[3], carry = bits.Add64(x[3], y[3], carry) return z, carry != 0 } // AddMod sets z to the sum ( x+y ) mod m, and returns z. // If m == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) AddMod(x, y, m *Int) *Int { if m.IsZero() { return z.Clear() } if z == m { // z is an alias for m // TODO: Understand why needed and add tests for all "division" methods. m = m.Clone() } if _, overflow := z.AddOverflow(x, y); overflow { sum := [5]uint64{z[0], z[1], z[2], z[3], 1} var quot [5]uint64 rem := udivrem(quot[:], sum[:], m) return z.Set(&rem) } return z.Mod(z, m) } // AddUint64 sets z to x + y, where y is a uint64, and returns z func (z *Int) AddUint64(x *Int, y uint64) *Int { var carry uint64 z[0], carry = bits.Add64(x[0], y, 0) z[1], carry = bits.Add64(x[1], 0, carry) z[2], carry = bits.Add64(x[2], 0, carry) z[3], _ = bits.Add64(x[3], 0, carry) return z } // PaddedBytes encodes a Int as a 0-padded byte slice. The length // of the slice is at least n bytes. // Example, z =1, n = 20 => [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] func (z *Int) PaddedBytes(n int) []byte { b := make([]byte, n) for i := 0; i < 32 && i < n; i++ { b[n-1-i] = byte(z[i/8] >> uint64(8*(i%8))) } return b } // SubUint64 set z to the difference x - y, where y is a uint64, and returns z func (z *Int) SubUint64(x *Int, y uint64) *Int { var carry uint64 z[0], carry = bits.Sub64(x[0], y, carry) z[1], carry = bits.Sub64(x[1], 0, carry) z[2], carry = bits.Sub64(x[2], 0, carry) z[3], _ = bits.Sub64(x[3], 0, carry) return z } // SubOverflow sets z to the difference x-y and returns z and true if the operation underflowed func (z *Int) SubOverflow(x, y *Int) (*Int, bool) { var carry uint64 z[0], carry = bits.Sub64(x[0], y[0], 0) z[1], carry = bits.Sub64(x[1], y[1], carry) z[2], carry = bits.Sub64(x[2], y[2], carry) z[3], carry = bits.Sub64(x[3], y[3], carry) return z, carry != 0 } // Sub sets z to the difference x-y func (z *Int) Sub(x, y *Int) *Int { var carry uint64 z[0], carry = bits.Sub64(x[0], y[0], 0) z[1], carry = bits.Sub64(x[1], y[1], carry) z[2], carry = bits.Sub64(x[2], y[2], carry) z[3], _ = bits.Sub64(x[3], y[3], carry) return z } // umulStep computes (hi * 2^64 + lo) = z + (x * y) + carry. func umulStep(z, x, y, carry uint64) (hi, lo uint64) { hi, lo = bits.Mul64(x, y) lo, carry = bits.Add64(lo, carry, 0) hi, _ = bits.Add64(hi, 0, carry) lo, carry = bits.Add64(lo, z, 0) hi, _ = bits.Add64(hi, 0, carry) return hi, lo } // umulHop computes (hi * 2^64 + lo) = z + (x * y) func umulHop(z, x, y uint64) (hi, lo uint64) { hi, lo = bits.Mul64(x, y) lo, carry := bits.Add64(lo, z, 0) hi, _ = bits.Add64(hi, 0, carry) return hi, lo } // umul computes full 256 x 256 -> 512 multiplication. func umul(x, y *Int) [8]uint64 { var ( res [8]uint64 carry, carry4, carry5, carry6 uint64 res1, res2, res3, res4, res5 uint64 ) carry, res[0] = bits.Mul64(x[0], y[0]) carry, res1 = umulHop(carry, x[1], y[0]) carry, res2 = umulHop(carry, x[2], y[0]) carry4, res3 = umulHop(carry, x[3], y[0]) carry, res[1] = umulHop(res1, x[0], y[1]) carry, res2 = umulStep(res2, x[1], y[1], carry) carry, res3 = umulStep(res3, x[2], y[1], carry) carry5, res4 = umulStep(carry4, x[3], y[1], carry) carry, res[2] = umulHop(res2, x[0], y[2]) carry, res3 = umulStep(res3, x[1], y[2], carry) carry, res4 = umulStep(res4, x[2], y[2], carry) carry6, res5 = umulStep(carry5, x[3], y[2], carry) carry, res[3] = umulHop(res3, x[0], y[3]) carry, res[4] = umulStep(res4, x[1], y[3], carry) carry, res[5] = umulStep(res5, x[2], y[3], carry) res[7], res[6] = umulStep(carry6, x[3], y[3], carry) return res } // Mul sets z to the product x*y func (z *Int) Mul(x, y *Int) *Int { var ( res Int carry uint64 res1, res2, res3 uint64 ) carry, res[0] = bits.Mul64(x[0], y[0]) carry, res1 = umulHop(carry, x[1], y[0]) carry, res2 = umulHop(carry, x[2], y[0]) res3 = x[3]*y[0] + carry carry, res[1] = umulHop(res1, x[0], y[1]) carry, res2 = umulStep(res2, x[1], y[1], carry) res3 = res3 + x[2]*y[1] + carry carry, res[2] = umulHop(res2, x[0], y[2]) res3 = res3 + x[1]*y[2] + carry res[3] = res3 + x[0]*y[3] return z.Set(&res) } // MulOverflow sets z to the product x*y, and returns z and whether overflow occurred func (z *Int) MulOverflow(x, y *Int) (*Int, bool) { p := umul(x, y) copy(z[:], p[:4]) return z, (p[4] | p[5] | p[6] | p[7]) != 0 } func (z *Int) squared() { var ( res Int carry0, carry1, carry2 uint64 res1, res2 uint64 ) carry0, res[0] = bits.Mul64(z[0], z[0]) carry0, res1 = umulHop(carry0, z[0], z[1]) carry0, res2 = umulHop(carry0, z[0], z[2]) carry1, res[1] = umulHop(res1, z[0], z[1]) carry1, res2 = umulStep(res2, z[1], z[1], carry1) carry2, res[2] = umulHop(res2, z[0], z[2]) res[3] = 2*(z[0]*z[3]+z[1]*z[2]) + carry0 + carry1 + carry2 z.Set(&res) } // isBitSet returns true if bit n-th is set, where n = 0 is LSB. // The n must be <= 255. func (z *Int) isBitSet(n uint) bool { return (z[n/64] & (1 << (n % 64))) != 0 } // addTo computes x += y. // Requires len(x) >= len(y). func addTo(x, y []uint64) uint64 { var carry uint64 for i := 0; i < len(y); i++ { x[i], carry = bits.Add64(x[i], y[i], carry) } return carry } // subMulTo computes x -= y * multiplier. // Requires len(x) >= len(y). func subMulTo(x, y []uint64, multiplier uint64) uint64 { var borrow uint64 for i := 0; i < len(y); i++ { s, carry1 := bits.Sub64(x[i], borrow, 0) ph, pl := bits.Mul64(y[i], multiplier) t, carry2 := bits.Sub64(s, pl, 0) x[i] = t borrow = ph + carry1 + carry2 } return borrow } // udivremBy1 divides u by single normalized word d and produces both quotient and remainder. // The quotient is stored in provided quot. func udivremBy1(quot, u []uint64, d uint64) (rem uint64) { reciprocal := reciprocal2by1(d) rem = u[len(u)-1] // Set the top word as remainder. for j := len(u) - 2; j >= 0; j-- { quot[j], rem = udivrem2by1(rem, u[j], d, reciprocal) } return rem } // udivremKnuth implements the division of u by normalized multiple word d from the Knuth's division algorithm. // The quotient is stored in provided quot - len(u)-len(d) words. // Updates u to contain the remainder - len(d) words. func udivremKnuth(quot, u, d []uint64) { dh := d[len(d)-1] dl := d[len(d)-2] reciprocal := reciprocal2by1(dh) for j := len(u) - len(d) - 1; j >= 0; j-- { u2 := u[j+len(d)] u1 := u[j+len(d)-1] u0 := u[j+len(d)-2] var qhat, rhat uint64 if u2 >= dh { // Division overflows. qhat = ^uint64(0) // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). } else { qhat, rhat = udivrem2by1(u2, u1, dh, reciprocal) ph, pl := bits.Mul64(qhat, dl) if ph > rhat || (ph == rhat && pl > u0) { qhat-- // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). } } // Multiply and subtract. borrow := subMulTo(u[j:], d, qhat) u[j+len(d)] = u2 - borrow if u2 < borrow { // Too much subtracted, add back. qhat-- u[j+len(d)] += addTo(u[j:], d) } quot[j] = qhat // Store quotient digit. } } // udivrem divides u by d and produces both quotient and remainder. // The quotient is stored in provided quot - len(u)-len(d)+1 words. // It loosely follows the Knuth's division algorithm (sometimes referenced as "schoolbook" division) using 64-bit words. // See Knuth, Volume 2, section 4.3.1, Algorithm D. func udivrem(quot, u []uint64, d *Int) (rem Int) { var dLen int for i := len(d) - 1; i >= 0; i-- { if d[i] != 0 { dLen = i + 1 break } } shift := uint(bits.LeadingZeros64(d[dLen-1])) var dnStorage Int dn := dnStorage[:dLen] for i := dLen - 1; i > 0; i-- { dn[i] = (d[i] << shift) | (d[i-1] >> (64 - shift)) } dn[0] = d[0] << shift var uLen int for i := len(u) - 1; i >= 0; i-- { if u[i] != 0 { uLen = i + 1 break } } var unStorage [9]uint64 un := unStorage[:uLen+1] un[uLen] = u[uLen-1] >> (64 - shift) for i := uLen - 1; i > 0; i-- { un[i] = (u[i] << shift) | (u[i-1] >> (64 - shift)) } un[0] = u[0] << shift // TODO: Skip the highest word of numerator if not significant. if dLen == 1 { r := udivremBy1(quot, un, dn[0]) rem.SetUint64(r >> shift) return rem } udivremKnuth(quot, un, dn) for i := 0; i < dLen-1; i++ { rem[i] = (un[i] >> shift) | (un[i+1] << (64 - shift)) } rem[dLen-1] = un[dLen-1] >> shift return rem } // Div sets z to the quotient x/y for returns z. // If y == 0, z is set to 0 func (z *Int) Div(x, y *Int) *Int { if y.IsZero() || y.Gt(x) { return z.Clear() } if x.Eq(y) { return z.SetOne() } // Shortcut some cases if x.IsUint64() { return z.SetUint64(x.Uint64() / y.Uint64()) } // At this point, we know // x/y ; x > y > 0 var quot Int udivrem(quot[:], x[:], y) return z.Set(") } // Mod sets z to the modulus x%y for y != 0 and returns z. // If y == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) Mod(x, y *Int) *Int { if x.IsZero() || y.IsZero() { return z.Clear() } switch x.Cmp(y) { case -1: // x < y copy(z[:], x[:]) return z case 0: // x == y return z.Clear() // They are equal } // At this point: // x != 0 // y != 0 // x > y // Shortcut trivial case if x.IsUint64() { return z.SetUint64(x.Uint64() % y.Uint64()) } var quot Int rem := udivrem(quot[:], x[:], y) return z.Set(&rem) } // SMod interprets x and y as two's complement signed integers, // sets z to (sign x) * { abs(x) modulus abs(y) } // If y == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) SMod(x, y *Int) *Int { ys := y.Sign() xs := x.Sign() // abs x if xs == -1 { x = new(Int).Neg(x) } // abs y if ys == -1 { y = new(Int).Neg(y) } z.Mod(x, y) if xs == -1 { z.Neg(z) } return z } // MulMod calculates the modulo-m multiplication of x and y and // returns z. // If m == 0, z is set to 0 (OBS: differs from the big.Int) func (z *Int) MulMod(x, y, m *Int) *Int { if x.IsZero() || y.IsZero() || m.IsZero() { return z.Clear() } p := umul(x, y) var ( pl Int ph Int ) copy(pl[:], p[:4]) copy(ph[:], p[4:]) // If the multiplication is within 256 bits use Mod(). if ph.IsZero() { return z.Mod(&pl, m) } var quot [8]uint64 rem := udivrem(quot[:], p[:], m) return z.Set(&rem) } // Abs interprets x as a two's complement signed number, // and sets z to the absolute value // Abs(0) = 0 // Abs(1) = 1 // Abs(2**255) = -2**255 // Abs(2**256-1) = -1 func (z *Int) Abs(x *Int) *Int { if x[3] < 0x8000000000000000 { return z.Set(x) } return z.Sub(new(Int), x) } // Neg returns -x mod 2**256. func (z *Int) Neg(x *Int) *Int { return z.Sub(new(Int), x) } // SDiv interprets n and d as two's complement signed integers, // does a signed division on the two operands and sets z to the result. // If d == 0, z is set to 0 func (z *Int) SDiv(n, d *Int) *Int { if n.Sign() > 0 { if d.Sign() > 0 { // pos / pos z.Div(n, d) return z } else { // pos / neg z.Div(n, new(Int).Neg(d)) return z.Neg(z) } } if d.Sign() < 0 { // neg / neg z.Div(new(Int).Neg(n), new(Int).Neg(d)) return z } // neg / pos z.Div(new(Int).Neg(n), d) return z.Neg(z) } // Sign returns: // -1 if z < 0 // 0 if z == 0 // +1 if z > 0 // Where z is interpreted as a two's complement signed number func (z *Int) Sign() int { if z.IsZero() { return 0 } if z[3] < 0x8000000000000000 { return 1 } return -1 } // BitLen returns the number of bits required to represent z func (z *Int) BitLen() int { switch { case z[3] != 0: return 192 + bits.Len64(z[3]) case z[2] != 0: return 128 + bits.Len64(z[2]) case z[1] != 0: return 64 + bits.Len64(z[1]) default: return bits.Len64(z[0]) } } // ByteLen returns the number of bytes required to represent z func (z *Int) ByteLen() int { return (z.BitLen() + 7) / 8 } func (z *Int) lsh64(x *Int) *Int { z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0 return z } func (z *Int) lsh128(x *Int) *Int { z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0 return z } func (z *Int) lsh192(x *Int) *Int { z[3], z[2], z[1], z[0] = x[0], 0, 0, 0 return z } func (z *Int) rsh64(x *Int) *Int { z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1] return z } func (z *Int) rsh128(x *Int) *Int { z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2] return z } func (z *Int) rsh192(x *Int) *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, x[3] return z } func (z *Int) srsh64(x *Int) *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, x[3], x[2], x[1] return z } func (z *Int) srsh128(x *Int) *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, x[3], x[2] return z } func (z *Int) srsh192(x *Int) *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, x[3] return z } // Not sets z = ^x and returns z. func (z *Int) Not(x *Int) *Int { z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0] return z } // Gt returns true if z > x func (z *Int) Gt(x *Int) bool { return x.Lt(z) } // Slt interprets z and x as signed integers, and returns // true if z < x func (z *Int) Slt(x *Int) bool { zSign := z.Sign() xSign := x.Sign() switch { case zSign >= 0 && xSign < 0: return false case zSign < 0 && xSign >= 0: return true default: return z.Lt(x) } } // Sgt interprets z and x as signed integers, and returns // true if z > x func (z *Int) Sgt(x *Int) bool { zSign := z.Sign() xSign := x.Sign() switch { case zSign >= 0 && xSign < 0: return true case zSign < 0 && xSign >= 0: return false default: return z.Gt(x) } } // Lt returns true if z < x func (z *Int) Lt(x *Int) bool { // z < x <=> z - x < 0 i.e. when subtraction overflows. _, carry := bits.Sub64(z[0], x[0], 0) _, carry = bits.Sub64(z[1], x[1], carry) _, carry = bits.Sub64(z[2], x[2], carry) _, carry = bits.Sub64(z[3], x[3], carry) return carry != 0 } // SetUint64 sets z to the value x func (z *Int) SetUint64(x uint64) *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, x return z } // Eq returns true if z == x func (z *Int) Eq(x *Int) bool { return (z[0] == x[0]) && (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3]) } // Cmp compares z and x and returns: // // -1 if z < x // 0 if z == x // +1 if z > x // func (z *Int) Cmp(x *Int) (r int) { if z.Gt(x) { return 1 } if z.Lt(x) { return -1 } return 0 } // LtUint64 returns true if z is smaller than n func (z *Int) LtUint64(n uint64) bool { return z[0] < n && (z[1]|z[2]|z[3]) == 0 } // GtUint64 returns true if z is larger than n func (z *Int) GtUint64(n uint64) bool { return z[0] > n || (z[1]|z[2]|z[3]) != 0 } // IsUint64 reports whether z can be represented as a uint64. func (z *Int) IsUint64() bool { return (z[1] | z[2] | z[3]) == 0 } // IsZero returns true if z == 0 func (z *Int) IsZero() bool { return (z[0] | z[1] | z[2] | z[3]) == 0 } // Clear sets z to 0 func (z *Int) Clear() *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, 0 return z } // SetAllOne sets all the bits of z to 1 func (z *Int) SetAllOne() *Int { z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, math.MaxUint64 return z } // SetOne sets z to 1 func (z *Int) SetOne() *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, 1 return z } // Lsh sets z = x << n and returns z. func (z *Int) Lsh(x *Int, n uint) *Int { // n % 64 == 0 if n&0x3f == 0 { switch n { case 0: return z.Set(x) case 64: return z.lsh64(x) case 128: return z.lsh128(x) case 192: return z.lsh192(x) default: return z.Clear() } } var ( a, b uint64 ) // Big swaps first switch { case n > 192: if n > 256 { return z.Clear() } z.lsh192(x) n -= 192 goto sh192 case n > 128: z.lsh128(x) n -= 128 goto sh128 case n > 64: z.lsh64(x) n -= 64 goto sh64 default: z.Set(x) } // remaining shifts a = z[0] >> (64 - n) z[0] = z[0] << n sh64: b = z[1] >> (64 - n) z[1] = (z[1] << n) | a sh128: a = z[2] >> (64 - n) z[2] = (z[2] << n) | b sh192: z[3] = (z[3] << n) | a return z } // Rsh sets z = x >> n and returns z. func (z *Int) Rsh(x *Int, n uint) *Int { // n % 64 == 0 if n&0x3f == 0 { switch n { case 0: return z.Set(x) case 64: return z.rsh64(x) case 128: return z.rsh128(x) case 192: return z.rsh192(x) default: return z.Clear() } } var ( a, b uint64 ) // Big swaps first switch { case n > 192: if n > 256 { return z.Clear() } z.rsh192(x) n -= 192 goto sh192 case n > 128: z.rsh128(x) n -= 128 goto sh128 case n > 64: z.rsh64(x) n -= 64 goto sh64 default: z.Set(x) } // remaining shifts a = z[3] << (64 - n) z[3] = z[3] >> n sh64: b = z[2] << (64 - n) z[2] = (z[2] >> n) | a sh128: a = z[1] << (64 - n) z[1] = (z[1] >> n) | b sh192: z[0] = (z[0] >> n) | a return z } // SRsh (Signed/Arithmetic right shift) // considers z to be a signed integer, during right-shift // and sets z = x >> n and returns z. func (z *Int) SRsh(x *Int, n uint) *Int { // If the MSB is 0, SRsh is same as Rsh. if !x.isBitSet(255) { return z.Rsh(x, n) } if n%64 == 0 { switch n { case 0: return z.Set(x) case 64: return z.srsh64(x) case 128: return z.srsh128(x) case 192: return z.srsh192(x) default: return z.SetAllOne() } } var ( a uint64 = math.MaxUint64 << (64 - n%64) ) // Big swaps first switch { case n > 192: if n > 256 { return z.SetAllOne() } z.srsh192(x) n -= 192 goto sh192 case n > 128: z.srsh128(x) n -= 128 goto sh128 case n > 64: z.srsh64(x) n -= 64 goto sh64 default: z.Set(x) } // remaining shifts z[3], a = (z[3]>>n)|a, z[3]<<(64-n) sh64: z[2], a = (z[2]>>n)|a, z[2]<<(64-n) sh128: z[1], a = (z[1]>>n)|a, z[1]<<(64-n) sh192: z[0] = (z[0] >> n) | a return z } // Set sets z to x and returns z. func (z *Int) Set(x *Int) *Int { *z = *x return z } // Or sets z = x | y and returns z. func (z *Int) Or(x, y *Int) *Int { z[0] = x[0] | y[0] z[1] = x[1] | y[1] z[2] = x[2] | y[2] z[3] = x[3] | y[3] return z } // And sets z = x & y and returns z. func (z *Int) And(x, y *Int) *Int { z[0] = x[0] & y[0] z[1] = x[1] & y[1] z[2] = x[2] & y[2] z[3] = x[3] & y[3] return z } // Xor sets z = x ^ y and returns z. func (z *Int) Xor(x, y *Int) *Int { z[0] = x[0] ^ y[0] z[1] = x[1] ^ y[1] z[2] = x[2] ^ y[2] z[3] = x[3] ^ y[3] return z } // Byte sets z to the value of the byte at position n, // with 'z' considered as a big-endian 32-byte integer // if 'n' > 32, f is set to 0 // Example: f = '5', n=31 => 5 func (z *Int) Byte(n *Int) *Int { // in z, z[0] is the least significant // if number, overflow := n.Uint64WithOverflow(); !overflow { if number < 32 { number := z[4-1-number/8] offset := (n[0] & 0x7) << 3 // 8*(n.d % 8) z[0] = (number & (0xff00000000000000 >> offset)) >> (56 - offset) z[3], z[2], z[1] = 0, 0, 0 return z } } return z.Clear() } // Exp sets z = base**exponent mod 2**256, and returns z. func (z *Int) Exp(base, exponent *Int) *Int { res := Int{1, 0, 0, 0} multiplier := *base expBitLen := exponent.BitLen() curBit := 0 word := exponent[0] for ; curBit < expBitLen && curBit < 64; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } word = exponent[1] for ; curBit < expBitLen && curBit < 128; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } word = exponent[2] for ; curBit < expBitLen && curBit < 192; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } word = exponent[3] for ; curBit < expBitLen && curBit < 256; curBit++ { if word&1 == 1 { res.Mul(&res, &multiplier) } multiplier.squared() word >>= 1 } return z.Set(&res) } // ExtendSign extends length of two’s complement signed integer, // sets z to // - x if byteNum > 31 // - x interpreted as a signed number with sign-bit at (byteNum*8+7), extended to the full 256 bits // and returns z. func (z *Int) ExtendSign(x, byteNum *Int) *Int { if byteNum.GtUint64(31) { return z.Set(x) } bit := uint(byteNum.Uint64()*8 + 7) mask := new(Int).SetOne() mask.Lsh(mask, bit) mask.SubUint64(mask, 1) if x.isBitSet(bit) { z.Or(x, mask.Not(mask)) } else { z.And(x, mask) } return z }