Search Apps Documentation Source Content File Folder Download Copy Actions Download

uint256.gno

6.11 Kb ยท 248 lines
  1package uint256
  2
  3import (
  4	"errors"
  5	"math/bits"
  6	"strconv"
  7)
  8
  9const (
 10	MAX_UINT64  = ^uint64(0)
 11	MAX_UINT256 = "115792089237316195423570985008687907853269984665640564039457584007913129639935"
 12)
 13
 14var ErrBig256Range = errors.New("decimal number > 256 bits")
 15
 16var (
 17	zero  = Uint{0, 0, 0, 0}
 18	one   = Uint{1, 0, 0, 0}
 19	two   = Uint{2, 0, 0, 0}
 20	three = Uint{3, 0, 0, 0}
 21)
 22
 23// Uint represents a 256-bit unsigned integer.
 24// It is stored as an array of 4 uint64 in little-endian order,
 25// where arr[0] is the least significant and arr[3] is the most significant.
 26type Uint [4]uint64
 27
 28// NewUint returns a new Uint initialized with the given uint64 value.
 29func NewUint(val uint64) *Uint {
 30	return &Uint{val, 0, 0, 0}
 31}
 32
 33// NewUintFromInt64 returns a new Uint initialized with the given int64 value.
 34// Panics if val is negative.
 35func NewUintFromInt64(val int64) *Uint {
 36	if val < 0 {
 37		panic("val is negative")
 38	}
 39	return &Uint{uint64(val), 0, 0, 0}
 40}
 41
 42// Zero returns a new Uint with value 0.
 43func Zero() *Uint {
 44	return &Uint{0, 0, 0, 0}
 45}
 46
 47// One returns a new Uint with value 1.
 48func One() *Uint {
 49	return &Uint{1, 0, 0, 0}
 50}
 51
 52// SetAllOne sets z to the maximum 256-bit value (all bits set to 1) and returns z.
 53func (z *Uint) SetAllOne() *Uint {
 54	z[3], z[2], z[1], z[0] = MAX_UINT64, MAX_UINT64, MAX_UINT64, MAX_UINT64
 55	return z
 56}
 57
 58// Set sets z to x and returns z.
 59func (z *Uint) Set(x *Uint) *Uint {
 60	*z = *x
 61	return z
 62}
 63
 64// SetOne sets z to 1 and returns z.
 65func (z *Uint) SetOne() *Uint {
 66	z[3], z[2], z[1], z[0] = 0, 0, 0, 1
 67	return z
 68}
 69
 70// SetFromDecimal sets z from a decimal string and returns an error if invalid.
 71// Accepts an optional leading "+" sign but rejects underscores and negative values.
 72// Returns ErrBig256Range if the number exceeds 256 bits.
 73func (z *Uint) SetFromDecimal(s string) (err error) {
 74	sLen := len(s)
 75	// Remove max one leading +
 76	if sLen > 0 && s[0] == '+' {
 77		s = s[1:]
 78		sLen--
 79	}
 80	// Remove any number of leading zeroes
 81	if sLen > 0 && s[0] == '0' {
 82		var i int
 83		var c rune
 84		for i, c = range s {
 85			if c != '0' {
 86				break
 87			}
 88		}
 89		s = s[i:]
 90		sLen = len(s)
 91	}
 92
 93	maxLen := len(MAX_UINT256)
 94	if sLen < maxLen {
 95		return z.fromDecimal(s)
 96	}
 97	if sLen == maxLen {
 98		if s > MAX_UINT256 {
 99			return ErrBig256Range
100		}
101		return z.fromDecimal(s)
102	}
103	return ErrBig256Range
104}
105
106// FromDecimal creates a new Uint from a decimal string.
107// Returns an error if the number exceeds 256 bits or is invalid.
108func FromDecimal(decimal string) (*Uint, error) {
109	var z Uint
110	if err := z.SetFromDecimal(decimal); err != nil {
111		return nil, err
112	}
113	return &z, nil
114}
115
116// MustFromDecimal creates a new Uint from a decimal string.
117// Panics if the string is invalid or the number exceeds 256 bits.
118func MustFromDecimal(decimal string) *Uint {
119	var z Uint
120	if err := z.SetFromDecimal(decimal); err != nil {
121		panic(err)
122	}
123	return &z
124}
125
126// multipliers holds the values that are needed for fromDecimal
127var multipliers = [5]Uint{
128	{0, 0, 0, 0},                                    // 1 (no multiplication needed in the first round)
129	{10000000000000000000, 0, 0, 0},                 // 10 ^ 19
130	{687399551400673280, 5421010862427522170, 0, 0}, // 10 ^ 38
131	{5332261958806667264, 17004971331911604867, 2938735877055718769, 0}, // 10 ^ 57
132	{0, 8607968719199866880, 532749306367912313, 1593091911132452277},   // 10 ^ 76
133}
134
135// fromDecimal parses a decimal string by processing it in 19-character chunks.
136// Each chunk is multiplied by the appropriate power of 10 and accumulated.
137func (z *Uint) fromDecimal(bs string) error {
138	// first clear the input
139	z.Clear()
140	// the maximum value of uint64 is 18446744073709551615, which is 20 characters
141	// one less means that a string of 19 9's is always within the uint64 limit
142	var (
143		num       uint64
144		err       error
145		remaining = len(bs)
146	)
147	if remaining == 0 {
148		return errors.New("EOF")
149	}
150
151	// We proceed in steps of 19 characters (nibbles), from least significant to most significant.
152	// This means that the first (up to) 19 characters do not need to be multiplied.
153	// In the second iteration, our slice of 19 characters needs to be multiplied
154	// by a factor of 10^19. Et cetera.
155	for i := range multipliers {
156		if remaining <= 0 {
157			return nil // Done
158		}
159		if remaining > 19 {
160			num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64)
161		} else {
162			// Final round
163			num, err = strconv.ParseUint(bs, 10, 64)
164		}
165		if err != nil {
166			return err
167		}
168		// add that number to our running total
169		if i == 0 {
170			z.SetUint64(num)
171		} else {
172			base := &Uint{uint64(num), 0, 0, 0}
173			// Check for overflow in multiplication
174			base, overflow := base.MulOverflow(base, &multipliers[i])
175			if overflow {
176				return ErrBig256Range
177			}
178			// Check for overflow in addition
179			base, overflow = base.AddOverflow(base, z)
180			if overflow {
181				return ErrBig256Range
182			}
183			z.Set(base)
184		}
185		// Chop off another 19 characters
186		if remaining > 19 {
187			bs = bs[0 : remaining-19]
188		}
189		remaining -= 19
190	}
191	return nil
192}
193
194// Byte returns the value of the byte at position n as a Uint.
195// Position n is counted from the right (0 = least significant byte).
196// Returns 0 if n >= 32.
197func (z *Uint) Byte(n *Uint) *Uint {
198	// in z, z[0] is the least significant
199	if number, overflow := n.Uint64WithOverflow(); !overflow {
200		if number < 32 {
201			number := z[4-1-number/8]
202			offset := (n[0] & 0x7) << 3 // 8*(n.d % 8)
203			z[0] = (number & (0xff00000000000000 >> offset)) >> (56 - offset)
204			z[3], z[2], z[1] = 0, 0, 0
205			return z
206		}
207	}
208
209	return z.Clear()
210}
211
212// BitLen returns the number of bits required to represent z.
213// BitLen(0) returns 0.
214func (z *Uint) BitLen() int {
215	switch {
216	case z[3] != 0:
217		return 192 + bits.Len64(z[3])
218	case z[2] != 0:
219		return 128 + bits.Len64(z[2])
220	case z[1] != 0:
221		return 64 + bits.Len64(z[1])
222	default:
223		return bits.Len64(z[0])
224	}
225}
226
227// ByteLen returns the number of bytes required to represent z.
228// ByteLen(0) returns 0.
229func (z *Uint) ByteLen() int {
230	return (z.BitLen() + 7) / 8
231}
232
233// Clear sets z to 0 and returns z.
234func (z *Uint) Clear() *Uint {
235	z[3], z[2], z[1], z[0] = 0, 0, 0, 0
236	return z
237}
238
239// Clone returns a new Uint with the same value as z.
240func (z *Uint) Clone() *Uint {
241	var x Uint
242	x[0] = z[0]
243	x[1] = z[1]
244	x[2] = z[2]
245	x[3] = z[3]
246
247	return &x
248}