Documentation ¶
Overview ¶
Package uint256 implements highly optimized fixed precision unsigned 256-bit integer arithmetic.
Example (BasicUsage) ¶
This example demonstrates calculating the result of dividing a max unsigned 256-bit integer by a max unsigned 128-bit integer and outputting that result in hex with leading zeros.
package main import ( "fmt" "github.com/sebitt27/dcrd/math/uint256" ) func main() { // Calculate maxUint256 / maxUint128 and output it in hex with leading zeros. maxUint128 := new(uint256.Uint256).SetUint64(1).Lsh(128).SubUint64(1) result := new(uint256.Uint256).Not().Div(maxUint128) fmt.Printf("result: %064x\n", result) }
Output: result: 0000000000000000000000000000000100000000000000000000000000000001
Index ¶
- type OutputBase
- type Uint256
- func (n *Uint256) Add(n2 *Uint256) *Uint256
- func (n *Uint256) Add2(n1, n2 *Uint256) *Uint256
- func (n *Uint256) AddUint64(n2 uint64) *Uint256
- func (n *Uint256) And(n2 *Uint256) *Uint256
- func (n *Uint256) BitLen() uint16
- func (n *Uint256) Bytes() [32]byte
- func (n *Uint256) BytesLE() [32]byte
- func (n *Uint256) Cmp(n2 *Uint256) int
- func (n *Uint256) CmpUint64(n2 uint64) int
- func (n *Uint256) Div(divisor *Uint256) *Uint256
- func (n *Uint256) Div2(dividend, divisor *Uint256) *Uint256
- func (n *Uint256) DivUint64(divisor uint64) *Uint256
- func (n *Uint256) Eq(n2 *Uint256) bool
- func (n *Uint256) EqUint64(n2 uint64) bool
- func (n Uint256) Format(s fmt.State, ch rune)
- func (n *Uint256) Gt(n2 *Uint256) bool
- func (n *Uint256) GtEq(n2 *Uint256) bool
- func (n *Uint256) GtEqUint64(n2 uint64) bool
- func (n *Uint256) GtUint64(n2 uint64) bool
- func (n *Uint256) IsOdd() bool
- func (n *Uint256) IsUint32() bool
- func (n *Uint256) IsUint64() bool
- func (n *Uint256) IsZero() bool
- func (n *Uint256) Lsh(bits uint32) *Uint256
- func (n *Uint256) LshVal(n2 *Uint256, bits uint32) *Uint256
- func (n *Uint256) Lt(n2 *Uint256) bool
- func (n *Uint256) LtEq(n2 *Uint256) bool
- func (n *Uint256) LtEqUint64(n2 uint64) bool
- func (n *Uint256) LtUint64(n2 uint64) bool
- func (n *Uint256) Mul(n2 *Uint256) *Uint256
- func (n *Uint256) Mul2(n1, n2 *Uint256) *Uint256
- func (n *Uint256) MulUint64(n2 uint64) *Uint256
- func (n *Uint256) Negate() *Uint256
- func (n *Uint256) NegateVal(n2 *Uint256) *Uint256
- func (n *Uint256) Not() *Uint256
- func (n *Uint256) Or(n2 *Uint256) *Uint256
- func (n *Uint256) PutBig(out *big.Int)
- func (n *Uint256) PutBytes(b *[32]byte)
- func (n *Uint256) PutBytesLE(b *[32]byte)
- func (n *Uint256) PutBytesUnchecked(b []byte)
- func (n *Uint256) PutBytesUncheckedLE(b []byte)
- func (n *Uint256) Rsh(bits uint32) *Uint256
- func (n *Uint256) RshVal(n2 *Uint256, bits uint32) *Uint256
- func (n *Uint256) Set(n2 *Uint256) *Uint256
- func (n *Uint256) SetBig(n2 *big.Int) *Uint256
- func (n *Uint256) SetByteSlice(b []byte) *Uint256
- func (n *Uint256) SetByteSliceLE(b []byte) *Uint256
- func (n *Uint256) SetBytes(b *[32]byte) *Uint256
- func (n *Uint256) SetBytesLE(b *[32]byte) *Uint256
- func (n *Uint256) SetUint64(n2 uint64) *Uint256
- func (n *Uint256) Square() *Uint256
- func (n *Uint256) SquareVal(n2 *Uint256) *Uint256
- func (n Uint256) String() string
- func (n *Uint256) Sub(n2 *Uint256) *Uint256
- func (n *Uint256) Sub2(n1, n2 *Uint256) *Uint256
- func (n *Uint256) SubUint64(n2 uint64) *Uint256
- func (n *Uint256) Text(base OutputBase) string
- func (n *Uint256) ToBig() *big.Int
- func (n *Uint256) Uint32() uint32
- func (n *Uint256) Uint64() uint64
- func (n *Uint256) Xor(n2 *Uint256) *Uint256
- func (n *Uint256) Zero()
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type OutputBase ¶
type OutputBase int
OutputBase represents a specific base to use for the string representation of a number.
const ( // OutputBaseBinary indicates a string representation of a uint256 in // base 2. OutputBaseBinary OutputBase = 2 // OutputBaseOctal indicates a string representation of a uint256 in base 8. OutputBaseOctal OutputBase = 8 // OutputBaseDecimal indicates a string representation of a uint256 in base // 10. OutputBaseDecimal OutputBase = 10 // OutputBaseHex indicates a string representation of a uint256 in base 16. OutputBaseHex OutputBase = 16 )
These constants define the supported output bases.
type Uint256 ¶
type Uint256 struct {
// contains filtered or unexported fields
}
Uint256 implements high-performance, zero-allocation, unsigned 256-bit fixed-precision arithmetic. All operations are performed modulo 2^256, so callers may rely on "wrap around" semantics.
It implements the primary arithmetic operations (addition, subtraction, multiplication, squaring, division, negation), bitwise operations (lsh, rsh, not, or, and, xor), comparison operations (equals, less, greater, cmp), interpreting and producing big and little endian bytes, and other convenience methods such as determining the minimum number of bits required to represent the current value, whether or not the value can be represented as a uint64 without loss of precision, and text formatting with base conversion.
Should it be absolutely necessary, conversion to the standard library math/big.Int can be accomplished by using the ToBig or PutBig methods. However, that should typically be avoided when possible as conversion to big.Ints requires allocations and is slower for every operation, often to a significant degree.
func (*Uint256) Add ¶
Add adds the passed uint256 to the existing one modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Add(n2).AddUin64(1) so that n = n + n2 + 1.
func (*Uint256) Add2 ¶
Add2 adds the passed two uint256s together modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Add2(n1, n2).AddUint64(1) so that n = n1 + n2 + 1.
func (*Uint256) AddUint64 ¶
AddUint64 adds the passed uint64 to the existing uint256 modulo 2^256 and stores the result in n.
The scalar is returned to support chaining. This enables syntax like: n.AddUint64(2).MulUint64(2) so that n = (n + 2) * 2.
func (*Uint256) And ¶
And computes the bitwise and of the uint256 and the passed uint256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.And(n2).AddUint64(1) so that n = (n & n2) + 1.
func (*Uint256) BitLen ¶
BitLen returns the minimum number of bits required to represent the uint256. The result is 0 when the value is 0.
func (*Uint256) Bytes ¶
Bytes unpacks the uint256 to a 32-byte big-endian array.
See PutBytes and PutBytesUnchecked for variants that allow an array or slice to be passed which can be useful to cut down on the number of allocations by allowing the caller to reuse a buffer or write directly into part of a larger buffer.
func (*Uint256) BytesLE ¶
BytesLE unpacks the uint256 to a 32-byte little-endian array.
See PutBytesLE and PutBytesUncheckedLE for variants that allow an array or slice to be passed which can be useful to cut down on the number of allocations by allowing the caller to reuse a buffer or write directly into part of a larger buffer.
func (*Uint256) Cmp ¶
Cmp compares the two uint256s and returns -1, 0, or 1 depending on whether the uint256 is less than, equal to, or greater than the given one.
That is, it returns:
-1 when n < n2 0 when n == n2 +1 when n > n2
func (*Uint256) CmpUint64 ¶
CmpUint64 compares the uint256 with the given uint64 and returns -1, 0, or 1 depending on whether the uint256 is less than, equal to, or greater than the uint64.
That is, it returns:
-1 when n < n2 0 when n == n2 +1 when n > n2
func (*Uint256) Div ¶
Div divides the existing value in n by the passed uint256 divisor modulo 2^256 and stores the result in n. It will panic if the divisor is 0.
This implements truncated division like native Go integers.
The uint256 is returned to support chaining. This enables syntax like: n.Div(n2).AddUint64(1) so that n = (n / n2) + 1.
func (*Uint256) Div2 ¶
Div2 divides the passed uint256 dividend by the passed uint256 divisor modulo 2^256 and stores the result in n. It will panic if the divisor is 0.
This implements truncated division like native Go integers and it is safe to alias the arguments.
The uint256 is returned to support chaining. This enables syntax like: n.Div2(n1, n2).AddUint64(1) so that n = (n1 / n2) + 1.
func (*Uint256) DivUint64 ¶
DivUint64 divides the existing value in n by the passed uint64 divisor modulo 2^256 and stores the result in n. It will panic if the divisor is 0.
This implements truncated division like native Go integers.
The uint256 is returned to support chaining. This enables syntax like: n.DivUint64(2).AddUint64(1) so that n = (n / 2) + 1.
func (*Uint256) EqUint64 ¶
EqUint64 returns whether or not the uint256 represents the same value as the given uint64.
func (Uint256) Format ¶
Format implements fmt.Formatter. It accepts the following format verbs:
'v' default format which is decimal 's' default string format which is decimal 'b' binary 'o' octal with 0 prefix when accompanied by # 'O' octal with 0o prefix 'd' decimal 'x' lowercase hexadecimal 'X' uppercase hexadecimal
It also supports the full suite of the fmt package format flags for integral types:
'#' output base prefix: binary: 0b (%#b) octal: 0 (%#o) hex: 0x (%#x) or 0X (%#X) '-' pad with spaces on the right (left-justify field) '0' pad with leading zeros rather than spaces
Finally, it supports specification of the minimum number of digits (precision) and output field width. Examples:
%#.64x default width, precision 64, lowercase hex with 0x prefix %256b width 256, default precision, binary with leading zeros %12.3O width 12, precision 3, octal with 0o prefix
func (*Uint256) Gt ¶
Gt returns whether or not the uint256 is greater than the given one. That is, it returns true when n > n2.
func (*Uint256) GtEq ¶
GtEq returns whether or not the uint256 is greater than or equal to the given one. That is, it returns true when n >= n2.
func (*Uint256) GtEqUint64 ¶
GtEqUint64 returns whether or not the uint256 is greater than or equal to the given uint64. That is, it returns true when n >= n2.
func (*Uint256) GtUint64 ¶
GtUint64 returns whether or not the uint256 is greater than the given uint64. That is, it returns true when n > n2.
func (*Uint256) IsUint32 ¶
IsUint32 returns whether or not the uint256 can be converted to a uint32 without any loss of precision. In other words, 0 <= n < 2^32.
func (*Uint256) IsUint64 ¶
IsUint64 returns whether or not the uint256 can be converted to a uint64 without any loss of precision. In other words, 0 <= n < 2^64.
func (*Uint256) Lsh ¶
Lsh shifts the uint256 to the left the given number of bits and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Lsh(2).AddUint64(1) so that n = (n << 2) + 1.
func (*Uint256) LshVal ¶
LshVal shifts the passed uint256 to the left the given number of bits and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.LshVal(n2, 2).AddUint64(1) so that n = (n2 << 2) + 1.
func (*Uint256) Lt ¶
Lt returns whether or not the uint256 is less than the given one. That is, it returns true when n < n2.
func (*Uint256) LtEq ¶
LtEq returns whether or not the uint256 is less than or equal to the given one. That is, it returns true when n <= n2.
func (*Uint256) LtEqUint64 ¶
LtEqUint64 returns whether or not the uint256 is less than or equal to the given uint64. That is, it returns true when n <= n2.
func (*Uint256) LtUint64 ¶
LtUint64 returns whether or not the uint256 is less than the given uint64. That is, it returns true when n < n2.
func (*Uint256) Mul ¶
Mul multiplies the passed uint256 by the existing value in n modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Mul(n2).AddUint64(1) so that n = (n * n2) + 1.
func (*Uint256) Mul2 ¶
Mul2 multiplies the passed uint256s together modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Mul2(n1, n2).AddUint64(1) so that n = (n1 * n2) + 1.
func (*Uint256) MulUint64 ¶
MulUint64 multiplies the uint256 by the passed uint64 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.MulUint64(2).Add(n2) so that n = 2 * n + n2.
func (*Uint256) Negate ¶
Negate negates the uint256 modulo 2^256. In other words, n will be set to its two's complement.
The uint256 is returned to support chaining. This enables syntax like: n.Negate().AddUint64(1) so that n = -n + 1.
func (*Uint256) NegateVal ¶
NegateVal negates the passed uint256 modulo 2^256 and stores the result in n. In other words, n will be set to the two's complement of the passed uint256.
The uint256 is returned to support chaining. This enables syntax like: n.NegateVal(n2).AddUint64(1) so that n = -n2 + 1.
func (*Uint256) Not ¶
Not computes the bitwise not of the uint256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Not().AddUint64(1) so that n = ^n + 1.
func (*Uint256) Or ¶
Or computes the bitwise or of the uint256 and the passed uint256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Or(n2).AddUint64(1) so that n = (n | n2) + 1.
func (*Uint256) PutBig ¶
PutBig sets the passed existing stdlib big integer to the value the uint256 currently represents.
This can sometimes be useful to reduce the number of allocations due to conversion if reusing the same variable is an option. The reason is that stdlib big integers internally allocate space on the heap to perform their operations and attempt to reuse that internal buffer when possible.
Do note however that even when reusing a big integer, it will naturally still require an allocation for the internal buffer unless it has already allocated one large enough to be reused. Moreover, they often require further allocations while performing arithmetic, notably multiplication and division.
Applications that are performance sensitive should consider avoiding conversion to big integers altogether when possible.
See ToBig for a variant that returns the uint256 as a new stdlib big integer instead which can sometimes be more ergonomic in contexts where additional allocations are not a concern.
func (*Uint256) PutBytes ¶
PutBytes unpacks the uint256 to a 32-byte big-endian value using the passed byte array.
There is a similar function, PutBytesUnchecked, which unpacks the uint256 into a slice that must have at least 32 bytes available. This version is provided since it can be useful to write directly into an array that is type checked.
Alternatively, there is also Bytes, which unpacks the uint256 into a new array and returns that which can sometimes be more ergonomic in applications that aren't concerned about an additional copy.
func (*Uint256) PutBytesLE ¶
PutBytesLE unpacks the uint256 to a 32-byte little-endian value using the passed byte array.
There is a similar function, PutBytesUncheckedLE, which unpacks the uint256 into a slice that must have at least 32 bytes available. This version is provided since it can be useful to write directly into an array that is type checked.
Alternatively, there is also BytesLE, which unpacks the uint256 into a new array and returns that which can sometimes be more ergonomic in applications that aren't concerned about an additional copy.
func (*Uint256) PutBytesUnchecked ¶
PutBytesUnchecked unpacks the uint256 to a 32-byte big-endian value directly into the passed byte slice. The target slice must have at least 32 bytes available or it will panic.
There is a similar function, PutBytes, which unpacks the uint256 into a 32-byte array directly. This version is provided since it can be useful to write directly into part of a larger buffer without needing a separate allocation.
func (*Uint256) PutBytesUncheckedLE ¶
PutBytesUncheckedLE unpacks the uint256 to a 32-byte little-endian value directly into the passed byte slice. The target slice must have at least 32 bytes available or it will panic.
There is a similar function, PutBytesLE, which unpacks the uint256 into a 32-byte array directly. This version is provided since it can be useful to write directly into part of a larger buffer without needing a separate allocation.
func (*Uint256) Rsh ¶
Rsh shifts the uint256 to the right the given number of bits and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Rsh(2).AddUint64(1) so that n = (n >> 2) + 1.
func (*Uint256) RshVal ¶
RshVal shifts the passed uint256 to the right the given number of bits and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.RshVal(n2, 2).AddUint64(1) so that n = (n2 >> 2) + 1.
func (*Uint256) Set ¶
Set sets the uint256 equal to the same value as the passed one.
The uint256 is returned to support chaining. This enables syntax like: n := new(Uint256).Set(n2).AddUint64(1) so that n = n2 + 1 where n2 is not modified.
func (*Uint256) SetBig ¶
SetBig sets the uint256 to the passed standard library big integer modulo 2^256.
The resulting uint256 will be set to the 2's complement of the provided value when it is negative.
The uint256 is returned to support chaining. This enables syntax like: n := new(Uint256).SetBig(n2).AddUint64(1) so that n = n2 + 1 where n2 is not modified.
PERFORMANCE NOTE: When the caller expects values to potentially be larger than a max uint256, it is _highly_ recommended to reduce the value mod 2^256 prior to calling this method for better performance.
The reason is that this method requires an allocation and copy when the provided big integer is larger than a max uint256 in order to reduce it without modifying the provided arg. The caller can avoid this allocation by performing the mod 2^256 prior to calling this method with the value.
More concretely, it is around 3 to 4 times faster to perform the reduction caller side as well as avoiding the allocation.
func (*Uint256) SetByteSlice ¶
SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned integer (meaning it is truncated to the final 32 bytes so that it is modulo 2^256), and sets the uint256 to the result.
The uint256 is returned to support chaining. This enables syntax like: n := new(Uint256).SetByteSlice(n2Slice).AddUint64(1) so that n = n2 + 1.
func (*Uint256) SetByteSliceLE ¶
SetByteSliceLE interprets the provided slice as a 256-bit little-endian unsigned integer (meaning it is truncated to the first 32 bytes so that it is modulo 2^256), and sets the uint256 to the result.
The uint256 is returned to support chaining. This enables syntax like: n := new(Uint256).SetByteSliceLE(n2Slice).AddUint64(1) so that n = n2 + 1.
func (*Uint256) SetBytes ¶
SetBytes interprets the provided array as a 256-bit big-endian unsigned integer and sets the uint256 to the result.
The uint256 is returned to support chaining. This enables syntax like: n := new(Uint256).SetBytes(n2Bytes).AddUint64(1) so that n = n2 + 1.
func (*Uint256) SetBytesLE ¶
SetBytesLE interprets the provided array as a 256-bit little-endian unsigned integer and sets the uint256 to the result.
func (*Uint256) SetUint64 ¶
SetUint64 sets the uint256 to the passed unsigned 64-bit integer. This is a convenience function since it is fairly common to perform arithmetic with small native integers.
The uint256 is returned to support chaining. This enables syntax like: n := new(Uint256).SetUint64(2).Mul(n2) so that n = 2 * n2.
func (*Uint256) Square ¶
Square squares the uint256 modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Square().Mul(n2) so that n = n^2 * n2.
func (*Uint256) SquareVal ¶
SquareVal squares the passed uint256 modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.SquareVal(n2).Mul(n2) so that n = n2^2 * n2 = n2^3.
func (*Uint256) Sub ¶
Sub subtracts the given uint256 from the existing one modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Sub(n2).AddUint64(1) so that n = n - n2 + 1.
func (*Uint256) Sub2 ¶
Sub2 subtracts the second given uint256 from the first modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.Sub2(n1, n2).AddUint64(1) so that n = n1 - n2 + 1.
func (*Uint256) SubUint64 ¶
SubUint64 subtracts the given uint64 from the uint256 modulo 2^256 and stores the result in n.
The uint256 is returned to support chaining. This enables syntax like: n.SubUint64(1).MulUint64(3) so that n = (n - 1) * 3.
func (*Uint256) Text ¶
func (n *Uint256) Text(base OutputBase) string
Text returns the string representation of the uint256 in the given base which must be on of the supported bases as defined by the OutputBase type.
It will return "<nil>" when the uint256 pointer is nil and a message that indicates the base is not supported along with the value in base 10 in the case the caller goes out of its way to call it with an invalid base.
func (*Uint256) ToBig ¶
ToBig returns the uint256 as a stdlib big integer.
Note that this is nearly guaranteed to cause two allocations. Applications that are performance sensitive should consider using PutBig instead or avoid conversion to big integers altogether when possible.
See PutBig for a variant that allows an existing big integer to be reused which can be useful to cut down on the number of allocations by allowing the caller to reuse a big integer that already has an internal buffer allocated.
func (*Uint256) Uint32 ¶
Uint32 returns the uint32 representation of the value. In other words, it returns the low-order 32 bits of the value as a uint32 which is equivalent to the value modulo 2^32. The caller can determine if this method can be used without truncation with the IsUint32 method.
func (*Uint256) Uint64 ¶
Uint64 returns the uint64 representation of the value. In other words, it returns the low-order 64 bits of the value as a uint64 which is equivalent to the value modulo 2^64. The caller can determine if this method can be used without truncation with the IsUint64 method.