Transaction
503515F4B97FC9…6014265EF9B7
Block 77,238 · index 0 · indexed
Summary
- Hash
- 503515F4B97FC9A919587153DB6697B0E1E419FC9B3DDA950F476014265EF9B7
- Block
- 77,238
- Size
- 33479 bytes
- Gas used
- 46,529,132 / 55,834,923
- Fee
- 55835ugnot
- Status
- success
Messages
- Package
- gno.land/p/gnoswap/int256/v1
Arguments · 15
- #1int256
- #2README.md
- #3# int256 256-bit signed integer arithmetic for GnoSwap. ## Overview Fixed-size 256-bit signed integer library optimized for AMM calculations. The unsuffixed `Add`, `Sub`, and `Mul` methods return the low 256 bits (two's-complement wrap). The `AddOverflow`, `SubOverflow`, and `MulOverflow` variants additionally report whether the signed operation overflowed. ## Features - Fixed 256-bit size (predictable gas costs) - Two's complement representation - Explicit overflow detection via `*Overflow` variants - AMM-optimized functions - Range: -(2^255) to 2^255-1 ## Usage ```go package main import i256 "gno.land/p/gnoswap/int256/v1" func main() { a := i256.NewInt(100) b := i256.MustFromDecimal("-1000") result, overflow := new(i256.Int).AddOverflow(a, b) if overflow { panic("signed addition overflow") } println(result.ToString()) // -900 } ``` ## Implementation The type shares a little-endian four-word representation with `uint256` and interoperates with it through conversion methods, but signed arithmetic is implemented independently.
- #4arithmetic.gno
- #5package int256 import "math/bits" 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 } } if uLen < dLen { copy(rem[:], u) return rem } 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 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 } func udivremBy1(quot, u []uint64, d uint64) (rem uint64) { reciprocal := reciprocal2by1(d) rem = u[len(u)-1] for j := len(u) - 2; j >= 0; j-- { quot[j], rem = udivrem2by1(rem, u[j], d, reciprocal) } return rem } func udivremKnuth(quot, u, d []uint64) { dLen := len(d) dh := d[dLen-1] dl := d[dLen-2] reciprocal := reciprocal2by1(dh) for j := len(u) - dLen - 1; j >= 0; j-- { u2 := u[j+dLen] u1 := u[j+dLen-1] u0 := u[j+dLen-2] var qhat, rhat uint64 if u2 >= dh { qhat = ^uint64(0) } else { qhat, rhat = udivrem2by1(u2, u1, dh, reciprocal) ph, pl := bits.Mul64(qhat, dl) if ph > rhat || (ph == rhat && pl > u0) { qhat-- } } borrow := subMulTo(u[j:], d, qhat) u[j+dLen] = u2 - borrow if u2 < borrow { qhat-- u[j+dLen] += addTo(u[j:], d) } quot[j] = qhat } } func reciprocal2by1(d uint64) uint64 { reciprocal, _ := bits.Div64(^d, ^uint64(0), d) return reciprocal } func udivrem2by1(uh, ul, d, reciprocal uint64) (quot, rem uint64) { qh, ql := bits.Mul64(reciprocal, uh) ql, carry := bits.Add64(ql, ul, 0) qh += uh + carry qh++ r := ul - qh*d if r > ql { qh-- r += d } if r >= d { qh++ r -= d } return qh, r } 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 } 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 }
- #6conversion.gno
- #7package int256 import ( "errors" "math/bits" "strconv" u256 "gno.land/p/gnoswap/uint256/v1" ) const ( maxAbsI256Dec = "57896044618658097711785492504343953926634992332820282019728792003956564819968" maxWords = 256 / bits.UintSize ) // MUST BE IMMUTABLE, DO NOT MODIFY // multipliers is a table of multipliers for the decimal conversion. var _multipliers = [5]*Int{ nil, {0x8ac7230489e80000, 0, 0, 0}, {0x98a224000000000, 0x4b3b4ca85a86c47a, 0, 0}, {0x4a00000000000000, 0xebfdcb54864ada83, 0x28c87cb5c89a2571, 0}, {0, 0x7775a5f171951000, 0x764b4abe8652979, 0x161bcca7119915b5}, } // FromDecimal parses a signed decimal string into a 256-bit integer. // // Parameters: // - decimal: the signed decimal text, optionally prefixed with + or - // // Returns: // - value: a parsed signed Int, or nil when parsing fails // - err: nil on success; otherwise an invalid-format or signed-256-bit-range error func FromDecimal(decimal string) (*Int, error) { z, err := new(Int).SetString(decimal) if err != nil { return nil, err } return z, nil } // MustFromDecimal parses a signed decimal string and panics on invalid input. // // Parameters: // - decimal: the signed decimal text, optionally prefixed with + or - // // Returns: // - result: a parsed signed Int; invalid or out-of-range input panics func MustFromDecimal(decimal string) *Int { z, err := FromDecimal(decimal) if err != nil { panic(err) } return z } // ToString returns the signed decimal representation of z. // // Returns: // - decimal: the signed base-10 representation of z func (z *Int) ToString() string { s := z.Sign() if s == 0 { return "0" } if z.IsInt64() { return strconv.FormatInt(z.Int64(), 10) } y := new(Int) if s > 0 { y.Set(z) } else { y.Neg(z) } var ( out = []byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") divisor = new(Int).SetUint64(10000000000000000000) pos = len(out) buf = make([]byte, 0, 19) ) for { var quot Int rem := udivrem(quot[:], y[:], divisor) y.Set(") buf = strconv.AppendUint(buf[:0], rem.Uint64(), 10) copy(out[pos-len(buf):], buf) if y.IsZero() { break } pos -= 19 } var res string if s < 0 { res = "-" } res += string(out[pos-len(buf):]) return res } // SetString parses a signed decimal string into an Int. // // Parameters: // - s: the signed decimal text to parse, with at most one leading sign // // Returns: // - value: the parsed signed Int, or nil when parsing fails // - err: nil on success; otherwise the parse or signed-256-bit-range error func (z *Int) SetString(s string) (*Int, error) { if len(s) == 0 { return nil, errors.New("int256: empty string") } isNeg := false switch s[0] { case '+': s = s[1:] case '-': isNeg = true s = s[1:] } if len(s) == 0 { return nil, errors.New("int256: empty string") } // Parallel comparison technique for validation // Process in 8-byte chunks for optimal performance sLen := len(s) i := 0 // Process 8 bytes at a time for i+7 < sLen { // Access up to s[i+7] is safe, then we can reduce the number of bounds checks _ = s[i+7] // Convert 8 bytes into a single uint64 // This method processes bytes directly, so no endianness issues chunk := uint64(s[i]) | uint64(s[i+1])<<8 chunk |= uint64(s[i+2])<<16 | uint64(s[i+3])<<24 chunk |= uint64(s[i+4])<<32 | uint64(s[i+5])<<40 chunk |= uint64(s[i+6])<<48 | uint64(s[i+7])<<56 // Check for '+' (0x2B) using SWAR technique // Subtracting 0x2B from each byte makes '+' bytes become 0 // Subtracting 0x01 makes bytes in ASCII range (0-127) have 0 in their highest bit // Therefore, AND with 0x80 to check for zero bytes plusTest := ((chunk ^ 0x2B2B2B2B2B2B2B2B) - 0x0101010101010101) & 0x8080808080808080 // Check for '-' (0x2D) using SWAR technique minusTest := ((chunk ^ 0x2D2D2D2D2D2D2D2D) - 0x0101010101010101) & 0x8080808080808080 // If either test is non-zero, a sign character exists if (plusTest | minusTest) != 0 { return nil, errors.New("int256: invalid sign in middle of number") } i += 8 } // Process remaining bytes for ; i < sLen; i++ { if s[i] == '+' || s[i] == '-' { return nil, errors.New("int256: invalid sign in middle of number") } } // Strip leading zeros if len(s) > 0 && s[0] == '0' { idx := 0 for idx < len(s) && s[idx] == '0' { idx++ } s = s[idx:] // If all characters were zeros, set to "0" if len(s) == 0 { s = "0" } } // Check for overflow if len(s) > len(maxAbsI256Dec) || (len(s) == len(maxAbsI256Dec) && s > maxAbsI256Dec) || (s == maxAbsI256Dec && !isNeg) { return nil, errors.New("int256: overflow") } if err := z.fromDecimal(s); err != nil { return nil, err } if isNeg { z.Neg(z) } return z, nil } func (z *Int) fromDecimal(bs string) error { z.Clear() var ( num uint64 err error remaining = len(bs) ) if remaining == 0 { return errors.New("EOF") } for i, mult := range _multipliers { if remaining <= 0 { return nil } if remaining > 19 { num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64) } else { num, err = strconv.ParseUint(bs, 10, 64) } if err != nil { return err } if i == 0 { z.SetUint64(num) } else { base := new(Int).SetUint64(num) z.Add(z, base.Mul(base, mult)) } if remaining > 19 { bs = bs[0 : remaining-19] } remaining -= 19 } return nil } // FromUint256 converts a uint256 to int256. // Panics if the uint256 value is greater than MaxInt256 (2^255 - 1). // // Parameters: // - x: the unsigned value to convert; values above MaxInt256 cause a panic // // Returns: // - result: a signed Int with the same value as x func FromUint256(x *u256.Uint) *Int { // Check overflow: if MSB of x[3] is set, value > MaxInt256 if x[3] > 0x7fffffffffffffff { panic("int256: overflow - uint256 value exceeds MaxInt256") } z := &Int{} z[0] = x[0] z[1] = x[1] z[2] = x[2] z[3] = x[3] return z }
- #8doc.gno
- #9// Package int256 implements 256-bit signed integer arithmetic for GnoSwap. // // This package provides an Int type that represents a 256-bit signed integer // using two's complement representation. It supports the full range from // -(2^255) to 2^255-1. The unsuffixed Add, Sub, and Mul methods return the // truncated 256-bit result; AddOverflow, SubOverflow, and MulOverflow also // return a signed-overflow flag. // // The implementation follows Ethereum's int256 semantics, ensuring compatibility // for cross-chain DeFi protocols. Operations are optimized for common AMM // calculations including tick math and price computations. package int256
- #10gnomod.toml
- #11module = "gno.land/p/gnoswap/int256/v1" gno = "0.9"
- #12int256.gno
- #13package int256 import ( "encoding/binary" "math" "math/bits" u256 "gno.land/p/gnoswap/uint256/v1" ) type Int [4]uint64 // Zero returns a fresh Int whose 256 bits are all zero. // // Returns: // - zero: A mutable *Int representing the signed value 0. func Zero() *Int { return &Int{} } // One returns a fresh Int representing the signed value 1. // // Returns: // - one: A mutable *Int with only its least-significant bit set. func One() *Int { return &Int{1, 0, 0, 0} } // MinInt256 returns the minimum signed 256-bit integer, -2^255. // // Returns: // - minimum: A fresh *Int containing the two's-complement minimum value. func MinInt256() *Int { return &Int{0, 0, 0, 0x8000000000000000} } // MaxInt256 returns the maximum signed 256-bit integer, 2^255 - 1. // // Returns: // - maximum: A fresh *Int containing the largest positive int256 value. func MaxInt256() *Int { return &Int{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff} } // NewInt constructs a signed 256-bit integer from an int64. // // Parameters: // - val: Signed 64-bit value to sign-extend into 256 bits. // // Returns: // - value: A fresh *Int representing val. func NewInt(val int64) *Int { z := &Int{} z.SetInt64(val) return z } // Set copies the complete 256-bit value from x into z. // // Parameters: // - x: Source Int whose four limbs are copied. // // Returns: // - z: The receiver after copying x. func (z *Int) Set(x *Int) *Int { z[0], z[1], z[2], z[3] = x[0], x[1], x[2], x[3] return z } // SetInt64 assigns x to z with two's-complement sign extension. // // Parameters: // - x: Signed 64-bit value to store. // // Returns: // - z: The receiver representing x as an Int. func (z *Int) SetInt64(x int64) *Int { if x >= 0 { z[3], z[2], z[1], z[0] = 0, 0, 0, uint64(x) return z } z[3], z[2], z[1], z[0] = 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, uint64(x) return z } // IsInt64 reports whether z can be represented exactly as a signed int64. // // Returns: // - fits: True when z is in [math.MinInt64, math.MaxInt64], false otherwise. func (z *Int) IsInt64() bool { return ((z[1]|z[2]|z[3]) == 0 && z[0] <= 0x7fffffffffffffff) || // zero or positive int64 ((z[1]&z[2]&z[3]) == 0xffffffffffffffff && z[0] >= 0x8000000000000000) // negative int64 } // Int64 converts z to int64 after checking its signed range. // // Returns: // - value: z's exact signed 64-bit value. // // Panics if z is outside the signed int64 range. func (z *Int) Int64() int64 { if !z.IsInt64() { panic("int256: int64 overflow") } s := z.Sign() if s == 0 { return 0 } if s > 0 { // overflow when z[0] > math.MaxInt64 return int64(z[0]) } // -(2^64 - z[0]) return -int64(math.MaxUint64 - z[0] + 1) } // SetUint64 assigns the non-negative uint64 x to z, clearing its upper limbs. // // Parameters: // - x: Unsigned 64-bit value to store. // // Returns: // - z: The receiver representing x as a non-negative Int. func (z *Int) SetUint64(x uint64) *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, x return z } // IsUint64 reports whether z fits in an unsigned 64-bit word. // // Returns: // - fits: True when all three upper 64-bit limbs of z are zero. func (z *Int) IsUint64() bool { return (z[1] | z[2] | z[3]) == 0 } // Uint64 converts z to uint64 when its upper 192 bits are zero. // // Returns: // - value: z's exact unsigned 64-bit value. // // Panics if any upper limb of z is non-zero. func (z *Int) Uint64() uint64 { if !z.IsUint64() { panic("int256: uint64 overflow") } return z[0] } // Abs returns the unsigned magnitude of z. // // Returns: // - magnitude: A *u256.Uint containing |z|; negative values are negated before conversion. // // Panics for MinInt256 because NegOverflow cannot represent its positive magnitude as Int. func (z *Int) Abs() *u256.Uint { if z.IsNeg() { neg := new(Int).NegOverflow(z) return &u256.Uint{neg[0], neg[1], neg[2], neg[3]} } return &u256.Uint{z[0], z[1], z[2], z[3]} } // Sign reports the signed sign of z. // // Returns: // - sign: -1 for negative z, 0 for zero z, or 1 for positive z. func (z *Int) Sign() int { if z.IsZero() { return 0 } if z[3]&0x8000000000000000 == 0 { return 1 } return -1 } // IsZero reports whether every limb of z is zero. // // Returns: // - isZero: True exactly when z represents the signed value 0. func (z *Int) IsZero() bool { return (z[0] | z[1] | z[2] | z[3]) == 0 } // IsOne reports whether z represents the signed value 1. // // Returns: // - isOne: True exactly when the low limb is 1 and all upper limbs are zero. func (z *Int) IsOne() bool { return (z[0] == 1) && (z[1]|z[2]|z[3]) == 0 } // IsNeg reports whether z has its signed two's-complement sign bit set. // // Returns: // - isNegative: True when z is negative, including MinInt256. func (z *Int) IsNeg() bool { return z[3]&0x8000000000000000 != 0 } // IsPositive reports whether z is strictly greater than zero. // // Returns: // - isPositive: True when the sign bit is clear and at least one value bit is set. func (z *Int) IsPositive() bool { return (z[3]&0x8000000000000000) == 0 && (z[3]|z[2]|z[1]|z[0]) != 0 } // IsMinI256 reports whether z equals MinInt256. // // Returns: // - isMinimum: True only for the bit pattern 0x8000...0000. func (z *Int) IsMinI256() bool { return (z[3] == 0x8000000000000000) && ((z[2] | z[1] | z[0]) == 0) } // NegOverflow computes the two's-complement negation of x and rejects the // one value whose positive magnitude is outside signed int256. // // Parameters: // - x: Signed 256-bit value to negate. // // Returns: // - z: The receiver containing -x. // // Panics when x is MinInt256. func (z *Int) NegOverflow(x *Int) *Int { if x[3] == 0x8000000000000000 && x[2] == 0 && x[1] == 0 && x[0] == 0 { panic("int256: overflow") } return z.Neg(x) } // Neg computes the two's-complement negation of x modulo 2^256. // // Parameters: // - x: 256-bit value whose bits are complemented and incremented. // // Returns: // - z: The receiver containing the wrapped negation of x. func (z *Int) Neg(x *Int) *Int { var carry uint64 z[0], z[1], z[2], z[3] = ^x[0], ^x[1], ^x[2], ^x[3] z[0], carry = bits.Add64(z[0], 1, 0) z[1], carry = bits.Add64(z[1], 0, carry) z[2], carry = bits.Add64(z[2], 0, carry) z[3] += carry return z } // Eq reports whether z and x have identical 256-bit representations. // // Parameters: // - x: Int to compare with z. // // Returns: // - equal: True when all four limbs match. func (z *Int) Eq(x *Int) bool { return (z[0] == x[0]) && (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3]) } // Neq reports whether z and x have different 256-bit representations. // // Parameters: // - x: Int to compare with z. // // Returns: // - different: True when at least one limb differs. func (z *Int) Neq(x *Int) bool { return !z.Eq(x) } // Add adds x and y modulo 2^256. // // Parameters: // - x: First signed 256-bit addend. // - y: Second signed 256-bit addend. // // Returns: // - z: The receiver containing the low 256 bits of 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] = x[3] + y[3] + carry return z } // AddOverflow adds x and y modulo 2^256 and reports signed overflow. // // Parameters: // - x: First signed 256-bit addend. // - y: Second signed 256-bit addend. // // Returns: // - z: The wrapped 256-bit sum. // - overflow: True when x and y have the same sign but the wrapped sum has the opposite sign. 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] = x[3] + y[3] + carry var overflow bool signX, signY, signZ := x.Sign(), y.Sign(), z.Sign() if (signX == signY) && (signX != signZ) { overflow = true } return z, overflow } // Sub subtracts y from x modulo 2^256. // // Parameters: // - x: Signed 256-bit minuend. // - y: Signed 256-bit subtrahend. // // Returns: // - z: The receiver containing the low 256 bits of 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] = x[3] - y[3] - carry return z } // SubOverflow subtracts y from x modulo 2^256 and reports signed overflow. // // Parameters: // - x: Signed 256-bit minuend. // - y: Signed 256-bit subtrahend. // // Returns: // - z: The wrapped 256-bit difference. // - overflow: True when the mathematical signed difference is outside the int256 range. 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] = x[3] - y[3] - carry var overflow bool signX, signY, signZ := x.Sign(), y.Sign(), z.Sign() if (signX == 0 && y.IsMinI256()) || ((signX != 0) && (signX != signY) && (signX != signZ)) { overflow = true } return z, overflow } // Mul multiplies x and y modulo 2^256. // // Parameters: // - x: First signed 256-bit factor. // - y: Second signed 256-bit factor. // // Returns: // - z: The receiver containing the low 256 bits of 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 multiplies x and y and reports whether the signed product exceeds int256. // The returned value is still the wrapped low 256-bit product. // // Parameters: // - x: First signed 256-bit factor. // - y: Second signed 256-bit factor. // // Returns: // - z: The low 256 bits of the signed product, with its sign restored. // - overflow: True when the mathematical product is outside [-2^255, 2^255 - 1]. func (z *Int) MulOverflow(x, y *Int) (*Int, bool) { if (x.IsMinI256() && y.IsOne()) || (x.IsOne() && y.IsMinI256()) { return z.Set(MinInt256()), false } var flipSign bool xSign, ySign := x.Sign(), y.Sign() if xSign*ySign == -1 { flipSign = true } xCopy := x.Clone() yCopy := y.Clone() if xSign < 0 { xCopy.Neg(xCopy) } if ySign < 0 { yCopy.Neg(yCopy) } p := umul(xCopy, yCopy) z[0], z[1], z[2], z[3] = p[0], p[1], p[2], p[3] var overflow bool if (p[4] | p[5] | p[6] | p[7]) != 0 { overflow = true } else if z.IsNeg() { // The 256th bit is set, which means the absolute value is >= 2^255 // This is only valid if the result should be exactly -2^255 if !flipSign || !z.IsMinI256() { overflow = true } } if flipSign { z.Neg(z) } return z, overflow } 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 } func umulStep(z, x, y, carry uint64) (hi, lo uint64) { hi, lo = bits.Mul64(x, y) lo, carry = bits.Add64(lo, carry, 0) hi += carry lo, carry = bits.Add64(lo, z, 0) hi += carry return hi, lo } func umulHop(z, x, y uint64) (hi, lo uint64) { hi, lo = bits.Mul64(x, y) lo, carry := bits.Add64(lo, z, 0) hi += carry return hi, lo } // Clear sets every limb of z to zero. // // Returns: // - z: The receiver representing the signed value 0. func (z *Int) Clear() *Int { z[0], z[1], z[2], z[3] = 0, 0, 0, 0 return z } // SetOne sets z to the signed value 1. // // Returns: // - z: The receiver with only its least-significant bit set. func (z *Int) SetOne() *Int { z[3], z[2], z[1], z[0] = 0, 0, 0, 1 return z } // SetAllBitsOne sets every bit of z to one, the two's-complement representation of -1. // // Returns: // - z: The receiver containing the all-ones 256-bit pattern. func (z *Int) SetAllBitsOne() *Int { z[0], z[1], z[2], z[3] = 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff return z } // Div divides signed 256-bit x by y, truncating the quotient toward zero. // // Parameters: // - x: Signed 256-bit dividend. // - y: Signed 256-bit divisor. // // Returns: // - z: The receiver containing the signed quotient x / y. // // Panics if y is zero. func (z *Int) Div(x, y *Int) *Int { if x.Sign() > 0 { if y.Sign() > 0 { return z.uquo(x, y) } z.uquo(x, new(Int).Neg(y)) return z.Neg(z) } if y.Sign() < 0 { return z.uquo(new(Int).Neg(x), new(Int).Neg(y)) } z.uquo(new(Int).Neg(x), y) return z.Neg(z) } func (z *Int) uquo(x, y *Int) *Int { if y.IsZero() { panic("zero division") } if x.IsZero() { return z.Clear() } if x.Eq(y) { return z.SetOne() } if x.IsInt64() && y.IsInt64() { return z.SetInt64(x.Int64() / y.Int64()) } quot := Int{} udivrem(quot[:], x[:], y) return z.Set(") } // Rem computes the signed remainder of x divided by y, preserving x's sign. // // Parameters: // - x: Signed 256-bit dividend. // - y: Signed 256-bit divisor. // // Returns: // - z: The receiver containing x % y, with magnitude less than |y|. // // Panics if y is zero. func (z *Int) Rem(x, y *Int) *Int { if x.Sign() > 0 { if y.Sign() > 0 { return z.urem(x, y) } return z.urem(x, new(Int).Neg(y)) } if y.Sign() < 0 { z.urem(new(Int).Neg(x), new(Int).Neg(y)) return z.Neg(z) } z.urem(new(Int).Neg(x), y) return z.Neg(z) } func (z *Int) urem(x, y *Int) *Int { if y.IsZero() { panic("zero division") } if x.IsZero() { return z.Clear() } if x.Eq(y) { return z.Clear() } if x.IsInt64() && y.IsInt64() { xInt64 := x.Int64() yInt64 := y.Int64() return z.SetInt64(xInt64 % yInt64) } quot := Int{} rem := udivrem(quot[:], x[:], y) return z.Set(&rem) } // Lt reports whether z is less than x as signed int256 values. // // Parameters: // - x: Signed 256-bit value to compare with z. // // Returns: // - less: True when z < x. func (z *Int) Lt(x *Int) bool { return z.Cmp(x) < 0 } // Lte reports whether z is less than or equal to x as signed int256 values. // // Parameters: // - x: Signed 256-bit value to compare with z. // // Returns: // - lessOrEqual: True when z <= x. func (z *Int) Lte(x *Int) bool { return z.Cmp(x) <= 0 } // Gt reports whether z is greater than x as signed int256 values. // // Parameters: // - x: Signed 256-bit value to compare with z. // // Returns: // - greater: True when z > x. func (z *Int) Gt(x *Int) bool { return z.Cmp(x) > 0 } // Gte reports whether z is greater than or equal to x as signed int256 values. // // Parameters: // - x: Signed 256-bit value to compare with z. // // Returns: // - greaterOrEqual: True when z >= x. func (z *Int) Gte(x *Int) bool { return z.Cmp(x) >= 0 } // Cmp compares z and x as signed two's-complement int256 values. // // Parameters: // - x: Signed 256-bit value to compare with z. // // Returns: // - comparison: -1 when z < x, 0 when z == x, and 1 when z > x. func (z *Int) Cmp(x *Int) int { zneg := int8(z[3] >> 63) xneg := int8(x[3] >> 63) if zneg != xneg { return int(xneg - zneg) } d0, carry := bits.Sub64(z[0], x[0], 0) d1, carry := bits.Sub64(z[1], x[1], carry) d2, carry := bits.Sub64(z[2], x[2], carry) d3, carry := bits.Sub64(z[3], x[3], carry) if carry == 1 { return -1 } if d0|d1|d2|d3 == 0 { return 0 } return 1 } // Clone returns an independent copy of z. // // Returns: // - clone: A fresh *Int with the same four limbs as z. func (z *Int) Clone() *Int { return &Int{z[0], z[1], z[2], z[3]} } // Or sets z to the bitwise OR of x and y. // // Parameters: // - x: First 256-bit operand. // - y: Second 256-bit operand. // // Returns: // - z: The receiver containing x | y. 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 to the bitwise AND of x and y. // // Parameters: // - x: First 256-bit operand. // - y: Second 256-bit operand. // // Returns: // - z: The receiver containing x & y. 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 to the bitwise exclusive OR of x and y. // // Parameters: // - x: First 256-bit operand. // - y: Second 256-bit operand. // // Returns: // - z: The receiver containing x ^ y. 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 } // Not sets z to the bitwise complement of x. // // Parameters: // - x: 256-bit operand whose bits are complemented. // // Returns: // - z: The receiver containing ^x. func (z *Int) Not(x *Int) *Int { z[0] = ^x[0] z[1] = ^x[1] z[2] = ^x[2] z[3] = ^x[3] return z } // Lsh sets z to x left-shifted by n bits, truncating to 256 bits. // // Parameters: // - x: 256-bit bit pattern to shift. // - n: Number of bit positions to shift left; n >= 256 yields zero. // // Returns: // - z: The receiver containing (x << n) modulo 2^256. func (z *Int) Lsh(x *Int, n uint) *Int { if n == 0 { return z.Set(x) } if n >= 256 { return z.Clear() } // Handle exact multiples of 64 separately to avoid 64-bit shift issues if n&0x3f == 0 { switch n { case 64: z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0 case 128: z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0 case 192: z[3], z[2], z[1], z[0] = x[0], 0, 0, 0 } return z } switch { case n > 192: n -= 192 z[3], z[2], z[1], z[0] = x[0]<<n, 0, 0, 0 case n > 128: n -= 128 z[3] = (x[1] << n) | (x[0] >> (64 - n)) z[2] = x[0] << n z[1], z[0] = 0, 0 case n > 64: n -= 64 z[3] = (x[2] << n) | (x[1] >> (64 - n)) z[2] = (x[1] << n) | (x[0] >> (64 - n)) z[1] = x[0] << n z[0] = 0 default: z[3] = (x[3] << n) | (x[2] >> (64 - n)) z[2] = (x[2] << n) | (x[1] >> (64 - n)) z[1] = (x[1] << n) | (x[0] >> (64 - n)) z[0] = x[0] << n } return z } // Rsh shifts x right by n bits using signed arithmetic semantics. // Non-negative values receive zero-fill; negative values receive sign extension. // // Parameters: // - x: Signed 256-bit value to shift. // - n: Number of bit positions to shift right. // // Returns: // - z: The receiver containing the arithmetic right shift of x. func (z *Int) Rsh(x *Int, n uint) *Int { if n == 0 { return z.Set(x) } if x.IsNeg() { return z.negRsh(x, n) } return z.rsh(x, n) } func (z *Int) rsh(x *Int, n uint) *Int { if n >= 256 { return z.Clear() } // Handle exact multiples of 64 separately to avoid 64-bit shift issues if n&0x3f == 0 { switch n { case 0: return z.Set(x) case 64: z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1] case 128: z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2] case 192: z[3], z[2], z[1], z[0] = 0, 0, 0, x[3] } return z } switch { case n > 192: n -= 192 z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]>>n case n > 128: n -= 128 z[3], z[2] = 0, 0 z[1] = x[3] >> n z[0] = (x[3] << (64 - n)) | (x[2] >> n) case n > 64: n -= 64 z[3] = 0 z[2] = x[3] >> n z[1] = (x[3] << (64 - n)) | (x[2] >> n) z[0] = (x[2] << (64 - n)) | (x[1] >> n) default: z[3] = x[3] >> n z[2] = (x[3] << (64 - n)) | (x[2] >> n) z[1] = (x[2] << (64 - n)) | (x[1] >> n) z[0] = (x[1] << (64 - n)) | (x[0] >> n) } return z } func (z *Int) negRsh(x *Int, n uint) *Int { if n >= 256 { return z.SetAllBitsOne() } var v uint64 = 0xffffffffffffffff // Handle exact multiples of 64 separately to avoid 64-bit shift issues if n&0x3f == 0 { switch n { case 0: return z.Set(x) case 64: z[3], z[2], z[1], z[0] = v, x[3], x[2], x[1] case 128: z[3], z[2], z[1], z[0] = v, v, x[3], x[2] case 192: z[3], z[2], z[1], z[0] = v, v, v, x[3] } return z } switch { case n > 192: n -= 192 z[3], z[2], z[1], z[0] = v, v, v, (v<<(64-n))|(x[3]>>n) case n > 128: n -= 128 z[3], z[2] = v, v z[1] = (v << (64 - n)) | (x[3] >> n) z[0] = (x[3] << (64 - n)) | (x[2] >> n) case n > 64: n -= 64 z[3] = v z[2] = (v << (64 - n)) | (x[3] >> n) z[1] = (x[3] << (64 - n)) | (x[2] >> n) z[0] = (x[2] << (64 - n)) | (x[1] >> n) default: z[3] = (v << (64 - n)) | (x[3] >> n) z[2] = (x[3] << (64 - n)) | (x[2] >> n) z[1] = (x[2] << (64 - n)) | (x[1] >> n) z[0] = (x[1] << (64 - n)) | (x[0] >> n) } return z } // BitLen returns the number of bits needed to represent z's raw 256-bit pattern. // // Returns: // - length: Bit length of the four-limb representation; zero has length 0 and // a negative value may require all 256 bits. 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]) } } // SetBytes32 loads the first 32 bytes of in as a big-endian 256-bit value. // // Parameters: // - in: Byte slice containing at least 32 bytes, with the most-significant byte first. // Bytes beyond the first 32 are ignored. // // Returns: // - z: The receiver populated from the 32-byte big-endian representation. // // Panics if in contains fewer than 32 bytes. func (z *Int) SetBytes32(in []byte) *Int { _ = in[31] // bounds check hint to compiler; see golang.org/issue/14808 z[3] = binary.BigEndian.Uint64(in[0:8]) z[2] = binary.BigEndian.Uint64(in[8:16]) z[1] = binary.BigEndian.Uint64(in[16:24]) z[0] = binary.BigEndian.Uint64(in[24:32]) return z }
- #14/gno.MemPackageType
- #15 MPUserAll
Result log
msg:0,success:true,log:,events:[]