- Kind
- Pure package
- Name
- v1
- Namespace
- gnoswap / int256
- Exported functions
- n/a — not supported for pure packages by the node (vm/qfuncs)
- Module
- gno.land/p/gnoswap/int256/v1
- gno
- 0.9
1package int25623import (4 "errors"5 "math/bits"6 "strconv"78
not supported for pure packages by the node (vm/qfuncs)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
u256 "gno.land/p/gnoswap/uint256/v1"
9)
10
11const (
12 maxAbsI256Dec = "57896044618658097711785492504343953926634992332820282019728792003956564819968"
13 maxWords = 256 / bits.UintSize
14)
15
16// MUST BE IMMUTABLE, DO NOT MODIFY
17// multipliers is a table of multipliers for the decimal conversion.
18var _multipliers = [5]*Int{
19 nil,
20 {0x8ac7230489e80000, 0, 0, 0},
21 {0x98a224000000000, 0x4b3b4ca85a86c47a, 0, 0},
22 {0x4a00000000000000, 0xebfdcb54864ada83, 0x28c87cb5c89a2571, 0},
23 {0, 0x7775a5f171951000, 0x764b4abe8652979, 0x161bcca7119915b5},
24}
25
26// FromDecimal parses a signed decimal string into a 256-bit integer.
27//
28// Parameters:
29// - decimal: the signed decimal text, optionally prefixed with + or -
30//
31// Returns:
32// - value: a parsed signed Int, or nil when parsing fails
33// - err: nil on success; otherwise an invalid-format or signed-256-bit-range error
34func FromDecimal(decimal string) (*Int, error) {
35 z, err := new(Int).SetString(decimal)
36 if err != nil {
37 return nil, err
38 }
39
40 return z, nil
41}
42
43// MustFromDecimal parses a signed decimal string and panics on invalid input.
44//
45// Parameters:
46// - decimal: the signed decimal text, optionally prefixed with + or -
47//
48// Returns:
49// - result: a parsed signed Int; invalid or out-of-range input panics
50func MustFromDecimal(decimal string) *Int {
51 z, err := FromDecimal(decimal)
52 if err != nil {
53 panic(err)
54 }
55 return z
56}
57
58// ToString returns the signed decimal representation of z.
59//
60// Returns:
61// - decimal: the signed base-10 representation of z
62func (z *Int) ToString() string {
63 s := z.Sign()
64 if s == 0 {
65 return "0"
66 }
67 if z.IsInt64() {
68 return strconv.FormatInt(z.Int64(), 10)
69 }
70 y := new(Int)
71 if s > 0 {
72 y.Set(z)
73 } else {
74 y.Neg(z)
75 }
76 var (
77 out = []byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
78 divisor = new(Int).SetUint64(10000000000000000000)
79 pos = len(out)
80 buf = make([]byte, 0, 19)
81 )
82
83 for {
84 var quot Int
85 rem := udivrem(quot[:], y[:], divisor)
86 y.Set(")
87 buf = strconv.AppendUint(buf[:0], rem.Uint64(), 10)
88 copy(out[pos-len(buf):], buf)
89 if y.IsZero() {
90 break
91 }
92 pos -= 19
93 }
94
95 var res string
96 if s < 0 {
97 res = "-"
98 }
99 res += string(out[pos-len(buf):])
100 return res
101}
102
103// SetString parses a signed decimal string into an Int.
104//
105// Parameters:
106// - s: the signed decimal text to parse, with at most one leading sign
107//
108// Returns:
109// - value: the parsed signed Int, or nil when parsing fails
110// - err: nil on success; otherwise the parse or signed-256-bit-range error
111func (z *Int) SetString(s string) (*Int, error) {
112 if len(s) == 0 {
113 return nil, errors.New("int256: empty string")
114 }
115
116 isNeg := false
117 switch s[0] {
118 case '+':
119 s = s[1:]
120 case '-':
121 isNeg = true
122 s = s[1:]
123 }
124
125 if len(s) == 0 {
126 return nil, errors.New("int256: empty string")
127 }
128
129 // Parallel comparison technique for validation
130 // Process in 8-byte chunks for optimal performance
131 sLen := len(s)
132 i := 0
133
134 // Process 8 bytes at a time
135 for i+7 < sLen {
136 // Access up to s[i+7] is safe, then we can reduce the number of bounds checks
137 _ = s[i+7]
138
139 // Convert 8 bytes into a single uint64
140 // This method processes bytes directly, so no endianness issues
141 chunk := uint64(s[i]) | uint64(s[i+1])<<8
142 chunk |= uint64(s[i+2])<<16 | uint64(s[i+3])<<24
143 chunk |= uint64(s[i+4])<<32 | uint64(s[i+5])<<40
144 chunk |= uint64(s[i+6])<<48 | uint64(s[i+7])<<56
145
146 // Check for '+' (0x2B) using SWAR technique
147 // Subtracting 0x2B from each byte makes '+' bytes become 0
148 // Subtracting 0x01 makes bytes in ASCII range (0-127) have 0 in their highest bit
149 // Therefore, AND with 0x80 to check for zero bytes
150 plusTest := ((chunk ^ 0x2B2B2B2B2B2B2B2B) - 0x0101010101010101) & 0x8080808080808080
151
152 // Check for '-' (0x2D) using SWAR technique
153 minusTest := ((chunk ^ 0x2D2D2D2D2D2D2D2D) - 0x0101010101010101) & 0x8080808080808080
154
155 // If either test is non-zero, a sign character exists
156 if (plusTest | minusTest) != 0 {
157 return nil, errors.New("int256: invalid sign in middle of number")
158 }
159
160 i += 8
161 }
162
163 // Process remaining bytes
164 for ; i < sLen; i++ {
165 if s[i] == '+' || s[i] == '-' {
166 return nil, errors.New("int256: invalid sign in middle of number")
167 }
168 }
169
170 // Strip leading zeros
171 if len(s) > 0 && s[0] == '0' {
172 idx := 0
173 for idx < len(s) && s[idx] == '0' {
174 idx++
175 }
176 s = s[idx:]
177 // If all characters were zeros, set to "0"
178 if len(s) == 0 {
179 s = "0"
180 }
181 }
182
183 // Check for overflow
184 if len(s) > len(maxAbsI256Dec) ||
185 (len(s) == len(maxAbsI256Dec) && s > maxAbsI256Dec) ||
186 (s == maxAbsI256Dec && !isNeg) {
187 return nil, errors.New("int256: overflow")
188 }
189
190 if err := z.fromDecimal(s); err != nil {
191 return nil, err
192 }
193
194 if isNeg {
195 z.Neg(z)
196 }
197
198 return z, nil
199}
200
201func (z *Int) fromDecimal(bs string) error {
202 z.Clear()
203 var (
204 num uint64
205 err error
206 remaining = len(bs)
207 )
208
209 if remaining == 0 {
210 return errors.New("EOF")
211 }
212
213 for i, mult := range _multipliers {
214 if remaining <= 0 {
215 return nil
216 }
217 if remaining > 19 {
218 num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64)
219 } else {
220 num, err = strconv.ParseUint(bs, 10, 64)
221 }
222 if err != nil {
223 return err
224 }
225 if i == 0 {
226 z.SetUint64(num)
227 } else {
228 base := new(Int).SetUint64(num)
229 z.Add(z, base.Mul(base, mult))
230 }
231 if remaining > 19 {
232 bs = bs[0 : remaining-19]
233 }
234 remaining -= 19
235 }
236 return nil
237}
238
239// FromUint256 converts a uint256 to int256.
240// Panics if the uint256 value is greater than MaxInt256 (2^255 - 1).
241//
242// Parameters:
243// - x: the unsigned value to convert; values above MaxInt256 cause a panic
244//
245// Returns:
246// - result: a signed Int with the same value as x
247func FromUint256(x *u256.Uint) *Int {
248 // Check overflow: if MSB of x[3] is set, value > MaxInt256
249 if x[3] > 0x7fffffffffffffff {
250 panic("int256: overflow - uint256 value exceeds MaxInt256")
251 }
252 z := &Int{}
253 z[0] = x[0]
254 z[1] = x[1]
255 z[2] = x[2]
256 z[3] = x[3]
257 return z
258}
259