1135 lines
24 KiB
Go
1135 lines
24 KiB
Go
// 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
|
||
}
|