Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

uint256.gno

8.14 Kb · 314 lines
  1package uint256
  2
  3import (
  4	"errors"
  5	"math/bits"
  6	"strconv"
  7)
  8
  9const ErrBig256Range = "decimal number > 256 bits"
 10
 11// Uint represents a 256-bit unsigned integer.
 12// It is stored as an array of 4 uint64 in little-endian order,
 13// where arr[0] is the least significant and arr[3] is the most significant.
 14type Uint [4]uint64
 15
 16// NewUint returns a new Uint initialized with the given uint64 value.
 17//
 18// Parameters:
 19//   - val: the initial uint64 value
 20//
 21// Returns:
 22//   - result: a new Uint initialized to val
 23func NewUint(val uint64) *Uint {
 24	return &Uint{val, 0, 0, 0}
 25}
 26
 27// NewUintFromInt64 returns a new Uint initialized with the given int64 value.
 28// Panics if val is negative.
 29//
 30// Parameters:
 31//   - val: the initial non-negative int64 value; a negative value panics
 32//
 33// Returns:
 34//   - result: a new Uint initialized to val
 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.
 43//
 44// Returns:
 45//   - result: a new zero-valued Uint
 46func Zero() *Uint {
 47	return &Uint{0, 0, 0, 0}
 48}
 49
 50// One returns a new Uint with value 1.
 51//
 52// Returns:
 53//   - result: a new Uint containing one
 54func One() *Uint {
 55	return &Uint{1, 0, 0, 0}
 56}
 57
 58// MaxUint256 returns the maximum 256-bit unsigned integer (2^256-1).
 59//
 60// Returns:
 61//   - result: a new Uint containing 2^256-1
 62func MaxUint256() *Uint {
 63	return &Uint{18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615}
 64}
 65
 66// SetAllOne sets z to the maximum 256-bit value (all bits set to 1) and returns z.
 67//
 68// Returns:
 69//   - result: z after setting every bit to one
 70func (z *Uint) SetAllOne() *Uint {
 71	z[3], z[2], z[1], z[0] = 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615
 72	return z
 73}
 74
 75// Set sets z to x and returns z.
 76//
 77// Parameters:
 78//   - x: the Uint value copied into z
 79//
 80// Returns:
 81//   - result: z after copying x
 82func (z *Uint) Set(x *Uint) *Uint {
 83	*z = *x
 84	return z
 85}
 86
 87// SetOne sets z to 1 and returns z.
 88//
 89// Returns:
 90//   - result: z after setting it to one
 91func (z *Uint) SetOne() *Uint {
 92	z[3], z[2], z[1], z[0] = 0, 0, 0, 1
 93	return z
 94}
 95
 96// SetFromDecimal sets z from a decimal string and returns an error if invalid.
 97// Accepts an optional leading "+" sign but rejects underscores and negative values.
 98// Returns ErrBig256Range if the number exceeds 256 bits.
 99//
100// Parameters:
101//   - s: the decimal text to parse; a leading + is accepted, while negatives and underscores are rejected
102//
103// Returns:
104//   - err: nil on success; otherwise the parse or range error
105func (z *Uint) SetFromDecimal(s string) (err error) {
106	sLen := len(s)
107	// Remove max one leading +
108	if sLen > 0 && s[0] == '+' {
109		s = s[1:]
110		sLen--
111	}
112	// Remove any number of leading zeroes
113	if sLen > 0 && s[0] == '0' {
114		var i int
115		var c rune
116		for i, c = range s {
117			if c != '0' {
118				break
119			}
120		}
121		s = s[i:]
122		sLen = len(s)
123	}
124
125	// maxUint256Str is the string representation of the maximum uint256 value.
126	maxUint256Str := "115792089237316195423570985008687907853269984665640564039457584007913129639935"
127
128	maxLen := len(maxUint256Str)
129	if sLen < maxLen {
130		return z.fromDecimal(s)
131	}
132	if sLen == maxLen {
133		if s > maxUint256Str {
134			return errors.New(ErrBig256Range)
135		}
136		return z.fromDecimal(s)
137	}
138	return errors.New(ErrBig256Range)
139}
140
141// FromDecimal creates a new Uint from a decimal string.
142// Returns an error if the number exceeds 256 bits or is invalid.
143//
144// Parameters:
145//   - decimal: the decimal text representing a non-negative value within 256 bits
146//
147// Returns:
148//   - value: a new parsed Uint, or nil on error
149//   - err: nil on success; otherwise an invalid-format or 256-bit-range error
150func FromDecimal(decimal string) (*Uint, error) {
151	var z Uint
152	if err := z.SetFromDecimal(decimal); err != nil {
153		return nil, err
154	}
155	return &z, nil
156}
157
158// MustFromDecimal creates a new Uint from a decimal string.
159// Panics if the string is invalid or the number exceeds 256 bits.
160//
161// Parameters:
162//   - decimal: the decimal text representing a non-negative value within 256 bits
163//
164// Returns:
165//   - result: a new parsed Uint; invalid or out-of-range input panics
166func MustFromDecimal(decimal string) *Uint {
167	var z Uint
168	if err := z.SetFromDecimal(decimal); err != nil {
169		panic(err)
170	}
171	return &z
172}
173
174// multipliers holds the values that are needed for fromDecimal
175var multipliers = [5]Uint{
176	{0, 0, 0, 0},                                    // 1 (no multiplication needed in the first round)
177	{10000000000000000000, 0, 0, 0},                 // 10 ^ 19
178	{687399551400673280, 5421010862427522170, 0, 0}, // 10 ^ 38
179	{5332261958806667264, 17004971331911604867, 2938735877055718769, 0}, // 10 ^ 57
180	{0, 8607968719199866880, 532749306367912313, 1593091911132452277},   // 10 ^ 76
181}
182
183// fromDecimal parses a decimal string by processing it in 19-character chunks.
184// Each chunk is multiplied by the appropriate power of 10 and accumulated.
185func (z *Uint) fromDecimal(bs string) error {
186	// first clear the input
187	z.Clear()
188	// the maximum value of uint64 is 18446744073709551615, which is 20 characters
189	// one less means that a string of 19 9's is always within the uint64 limit
190	var (
191		num       uint64
192		err       error
193		remaining = len(bs)
194	)
195	if remaining == 0 {
196		return errors.New("EOF")
197	}
198
199	// We proceed in steps of 19 characters (nibbles), from least significant to most significant.
200	// This means that the first (up to) 19 characters do not need to be multiplied.
201	// In the second iteration, our slice of 19 characters needs to be multiplied
202	// by a factor of 10^19. Et cetera.
203	for i := range multipliers {
204		if remaining <= 0 {
205			return nil // Done
206		}
207		if remaining > 19 {
208			num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64)
209		} else {
210			// Final round
211			num, err = strconv.ParseUint(bs, 10, 64)
212		}
213		if err != nil {
214			return err
215		}
216		// add that number to our running total
217		if i == 0 {
218			z.SetUint64(num)
219		} else {
220			base := &Uint{uint64(num), 0, 0, 0}
221			// Check for overflow in multiplication
222			base, overflow := base.MulOverflow(base, &multipliers[i])
223			if overflow {
224				return errors.New(ErrBig256Range)
225			}
226			// Check for overflow in addition
227			base, overflow = base.AddOverflow(base, z)
228			if overflow {
229				return errors.New(ErrBig256Range)
230			}
231			z.Set(base)
232		}
233		// Chop off another 19 characters
234		if remaining > 19 {
235			bs = bs[0 : remaining-19]
236		}
237		remaining -= 19
238	}
239	return nil
240}
241
242// Byte returns the value of the byte at position n as a Uint.
243// Position n is counted from the left (0 = most significant byte).
244// Returns 0 if n >= 32.
245//
246// Parameters:
247//   - n: the zero-based byte position counted from the most-significant byte; positions 32 and above yield zero
248//
249// Returns:
250//   - result: z containing the selected byte as a Uint, or zero when n is outside the 32-byte value
251func (z *Uint) Byte(n *Uint) *Uint {
252	// in z, z[0] is the least significant
253	if number, overflow := n.Uint64WithOverflow(); !overflow {
254		if number < 32 {
255			number := z[4-1-number/8]
256			offset := (n[0] & 0x7) << 3 // 8*(n.d % 8)
257			z[0] = (number & (0xff00000000000000 >> offset)) >> (56 - offset)
258			z[3], z[2], z[1] = 0, 0, 0
259			return z
260		}
261	}
262
263	return z.Clear()
264}
265
266// BitLen returns the number of bits required to represent z.
267// BitLen(0) returns 0.
268//
269// Returns:
270//   - bits: the number of significant bits in z, with zero represented by 0
271func (z *Uint) BitLen() int {
272	switch {
273	case z[3] != 0:
274		return 192 + bits.Len64(z[3])
275	case z[2] != 0:
276		return 128 + bits.Len64(z[2])
277	case z[1] != 0:
278		return 64 + bits.Len64(z[1])
279	default:
280		return bits.Len64(z[0])
281	}
282}
283
284// ByteLen returns the number of bytes required to represent z.
285// ByteLen(0) returns 0.
286//
287// Returns:
288//   - bytes: the number of bytes needed to represent z, with zero represented by 0
289func (z *Uint) ByteLen() int {
290	return (z.BitLen() + 7) / 8
291}
292
293// Clear sets z to 0 and returns z.
294//
295// Returns:
296//   - result: z after setting it to zero
297func (z *Uint) Clear() *Uint {
298	z[3], z[2], z[1], z[0] = 0, 0, 0, 0
299	return z
300}
301
302// Clone returns a new Uint with the same value as z.
303//
304// Returns:
305//   - result: a newly allocated Uint with the same value as z
306func (z *Uint) Clone() *Uint {
307	var x Uint
308	x[0] = z[0]
309	x[1] = z[1]
310	x[2] = z[2]
311	x[3] = z[3]
312
313	return &x
314}