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

int256.gno

12.58 Kb · 621 lines
  1package int256
  2
  3import (
  4	"encoding/binary"
  5	"math"
  6	"math/bits"
  7
  8	u256 "gno.land/p/gnoswap/uint256"
  9)
 10
 11type Int [4]uint64
 12
 13func Zero() *Int {
 14	return &Int{}
 15}
 16
 17func One() *Int {
 18	return &Int{1, 0, 0, 0}
 19}
 20
 21func MinInt256() *Int {
 22	return &Int{0, 0, 0, 0x8000000000000000}
 23}
 24
 25func MaxInt256() *Int {
 26	return &Int{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff}
 27}
 28
 29func NewInt(val int64) *Int {
 30	z := &Int{}
 31	z.SetInt64(val)
 32	return z
 33}
 34
 35func (z *Int) Set(x *Int) *Int {
 36	z[0], z[1], z[2], z[3] = x[0], x[1], x[2], x[3]
 37	return z
 38}
 39
 40func (z *Int) SetInt64(x int64) *Int {
 41	if x >= 0 {
 42		z[3], z[2], z[1], z[0] = 0, 0, 0, uint64(x)
 43		return z
 44	}
 45
 46	z[3], z[2], z[1], z[0] = 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, uint64(x)
 47	return z
 48}
 49
 50func (z *Int) IsInt64() bool {
 51	return ((z[1]|z[2]|z[3]) == 0 && z[0] <= 0x7fffffffffffffff) || // zero or positive int64
 52		((z[1]&z[2]&z[3]) == 0xffffffffffffffff && z[0] >= 0x8000000000000000) // negative int64
 53}
 54
 55func (z *Int) Int64() int64 {
 56	if !z.IsInt64() {
 57		panic("int256: int64 overflow")
 58	}
 59	s := z.Sign()
 60	if s == 0 {
 61		return 0
 62	}
 63	if s > 0 {
 64		// overflow when z[0] > math.MaxInt64
 65		return int64(z[0])
 66	}
 67	// -(2^64 - z[0])
 68	return -int64(math.MaxUint64 - z[0] + 1)
 69}
 70
 71func (z *Int) SetUint64(x uint64) *Int {
 72	z[3], z[2], z[1], z[0] = 0, 0, 0, x
 73	return z
 74}
 75
 76func (z *Int) IsUint64() bool {
 77	return (z[1] | z[2] | z[3]) == 0
 78}
 79
 80func (z *Int) Uint64() uint64 {
 81	if !z.IsUint64() {
 82		panic("int256: uint64 overflow")
 83	}
 84	return z[0]
 85}
 86
 87func (z *Int) Abs() *u256.Uint {
 88	if z.IsNeg() {
 89		neg := new(Int).NegOverflow(z)
 90		return &u256.Uint{neg[0], neg[1], neg[2], neg[3]}
 91	}
 92	return &u256.Uint{z[0], z[1], z[2], z[3]}
 93}
 94
 95func (z *Int) Sign() int {
 96	if z.IsZero() {
 97		return 0
 98	}
 99	if z[3]&0x8000000000000000 == 0 {
100		return 1
101	}
102	return -1
103}
104
105func (z *Int) IsZero() bool {
106	return (z[0] | z[1] | z[2] | z[3]) == 0
107}
108
109func (z *Int) IsOne() bool {
110	return (z[0] == 1) && (z[1]|z[2]|z[3]) == 0
111}
112
113func (z *Int) IsNeg() bool {
114	return z[3]&0x8000000000000000 != 0
115}
116
117func (z *Int) IsPositive() bool {
118	return (z[3]&0x8000000000000000) == 0 && (z[3]|z[2]|z[1]|z[0]) != 0
119}
120
121func (z *Int) IsMinI256() bool {
122	return (z[3] == 0x8000000000000000) && ((z[2] | z[1] | z[0]) == 0)
123}
124
125func (z *Int) NegOverflow(x *Int) *Int {
126	if x[3] == 0x8000000000000000 && x[2] == 0 && x[1] == 0 && x[0] == 0 {
127		panic("int256: overflow")
128	}
129
130	return z.Neg(x)
131}
132
133func (z *Int) Neg(x *Int) *Int {
134	var carry uint64
135	z[0], z[1], z[2], z[3] = ^x[0], ^x[1], ^x[2], ^x[3]
136	z[0], carry = bits.Add64(z[0], 1, 0)
137	z[1], carry = bits.Add64(z[1], 0, carry)
138	z[2], carry = bits.Add64(z[2], 0, carry)
139	z[3] += carry
140	return z
141}
142
143func (z *Int) Eq(x *Int) bool {
144	return (z[0] == x[0]) && (z[1] == x[1]) && (z[2] == x[2]) && (z[3] == x[3])
145}
146
147func (z *Int) Neq(x *Int) bool {
148	return !z.Eq(x)
149}
150
151func (z *Int) Add(x, y *Int) *Int {
152	var carry uint64
153	z[0], carry = bits.Add64(x[0], y[0], 0)
154	z[1], carry = bits.Add64(x[1], y[1], carry)
155	z[2], carry = bits.Add64(x[2], y[2], carry)
156	z[3] = x[3] + y[3] + carry
157	return z
158}
159
160func (z *Int) AddOverflow(x, y *Int) (*Int, bool) {
161	var carry uint64
162	z[0], carry = bits.Add64(x[0], y[0], 0)
163	z[1], carry = bits.Add64(x[1], y[1], carry)
164	z[2], carry = bits.Add64(x[2], y[2], carry)
165	z[3] = x[3] + y[3] + carry
166	var overflow bool
167	signX, signY, signZ := x.Sign(), y.Sign(), z.Sign()
168	if (signX == signY) && (signX != signZ) {
169		overflow = true
170	}
171	return z, overflow
172}
173
174func (z *Int) Sub(x, y *Int) *Int {
175	var carry uint64
176	z[0], carry = bits.Sub64(x[0], y[0], 0)
177	z[1], carry = bits.Sub64(x[1], y[1], carry)
178	z[2], carry = bits.Sub64(x[2], y[2], carry)
179	z[3] = x[3] - y[3] - carry
180	return z
181}
182
183func (z *Int) SubOverflow(x, y *Int) (*Int, bool) {
184	var carry uint64
185	z[0], carry = bits.Sub64(x[0], y[0], 0)
186	z[1], carry = bits.Sub64(x[1], y[1], carry)
187	z[2], carry = bits.Sub64(x[2], y[2], carry)
188	z[3] = x[3] - y[3] - carry
189	var overflow bool
190	signX, signY, signZ := x.Sign(), y.Sign(), z.Sign()
191	if (signX == 0 && y.IsMinI256()) || ((signX != 0) && (signX != signY) && (signX != signZ)) {
192		overflow = true
193	}
194	return z, overflow
195}
196
197func (z *Int) Mul(x, y *Int) *Int {
198	var (
199		res              Int
200		carry            uint64
201		res1, res2, res3 uint64
202	)
203
204	carry, res[0] = bits.Mul64(x[0], y[0])
205	carry, res1 = umulHop(carry, x[1], y[0])
206	carry, res2 = umulHop(carry, x[2], y[0])
207	res3 = x[3]*y[0] + carry
208
209	carry, res[1] = umulHop(res1, x[0], y[1])
210	carry, res2 = umulStep(res2, x[1], y[1], carry)
211	res3 = res3 + x[2]*y[1] + carry
212
213	carry, res[2] = umulHop(res2, x[0], y[2])
214	res3 = res3 + x[1]*y[2] + carry
215
216	res[3] = res3 + x[0]*y[3]
217
218	return z.Set(&res)
219}
220
221func (z *Int) MulOverflow(x, y *Int) (*Int, bool) {
222	if (x.IsMinI256() && y.IsOne()) || (x.IsOne() && y.IsMinI256()) {
223		return z.Set(MinInt256()), false
224	}
225
226	var flipSign bool
227	xSign, ySign := x.Sign(), y.Sign()
228	if xSign*ySign == -1 {
229		flipSign = true
230	}
231
232	xCopy := x.Clone()
233	yCopy := y.Clone()
234
235	if xSign < 0 {
236		xCopy.Neg(xCopy)
237	}
238	if ySign < 0 {
239		yCopy.Neg(yCopy)
240	}
241
242	p := umul(xCopy, yCopy)
243	z[0], z[1], z[2], z[3] = p[0], p[1], p[2], p[3]
244
245	var overflow bool
246	if (p[4] | p[5] | p[6] | p[7]) != 0 {
247		overflow = true
248	} else if z.IsNeg() {
249		// The 256th bit is set, which means the absolute value is >= 2^255
250		// This is only valid if the result should be exactly -2^255
251		if !flipSign || !z.IsMinI256() {
252			overflow = true
253		}
254	}
255
256	if flipSign {
257		z.Neg(z)
258	}
259
260	return z, overflow
261}
262
263func umul(x, y *Int) [8]uint64 {
264	var (
265		res                           [8]uint64
266		carry, carry4, carry5, carry6 uint64
267		res1, res2, res3, res4, res5  uint64
268	)
269
270	carry, res[0] = bits.Mul64(x[0], y[0])
271	carry, res1 = umulHop(carry, x[1], y[0])
272	carry, res2 = umulHop(carry, x[2], y[0])
273	carry4, res3 = umulHop(carry, x[3], y[0])
274
275	carry, res[1] = umulHop(res1, x[0], y[1])
276	carry, res2 = umulStep(res2, x[1], y[1], carry)
277	carry, res3 = umulStep(res3, x[2], y[1], carry)
278	carry5, res4 = umulStep(carry4, x[3], y[1], carry)
279
280	carry, res[2] = umulHop(res2, x[0], y[2])
281	carry, res3 = umulStep(res3, x[1], y[2], carry)
282	carry, res4 = umulStep(res4, x[2], y[2], carry)
283	carry6, res5 = umulStep(carry5, x[3], y[2], carry)
284
285	carry, res[3] = umulHop(res3, x[0], y[3])
286	carry, res[4] = umulStep(res4, x[1], y[3], carry)
287	carry, res[5] = umulStep(res5, x[2], y[3], carry)
288	res[7], res[6] = umulStep(carry6, x[3], y[3], carry)
289
290	return res
291}
292
293func umulStep(z, x, y, carry uint64) (hi, lo uint64) {
294	hi, lo = bits.Mul64(x, y)
295	lo, carry = bits.Add64(lo, carry, 0)
296	hi += carry
297	lo, carry = bits.Add64(lo, z, 0)
298	hi += carry
299	return hi, lo
300}
301
302func umulHop(z, x, y uint64) (hi, lo uint64) {
303	hi, lo = bits.Mul64(x, y)
304	lo, carry := bits.Add64(lo, z, 0)
305	hi += carry
306	return hi, lo
307}
308
309func (z *Int) Clear() *Int {
310	z[0], z[1], z[2], z[3] = 0, 0, 0, 0
311	return z
312}
313
314func (z *Int) SetOne() *Int {
315	z[3], z[2], z[1], z[0] = 0, 0, 0, 1
316	return z
317}
318
319func (z *Int) SetAllBitsOne() *Int {
320	z[0], z[1], z[2], z[3] = 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
321	return z
322}
323
324func (z *Int) Div(x, y *Int) *Int {
325	if x.Sign() > 0 {
326		if y.Sign() > 0 {
327			return z.uquo(x, y)
328		}
329		z.uquo(x, new(Int).Neg(y))
330		return z.Neg(z)
331	}
332	if y.Sign() < 0 {
333		return z.uquo(new(Int).Neg(x), new(Int).Neg(y))
334	}
335	z.uquo(new(Int).Neg(x), y)
336	return z.Neg(z)
337}
338
339func (z *Int) uquo(x, y *Int) *Int {
340	if y.IsZero() {
341		panic("zero division")
342	}
343	if x.IsZero() {
344		return z.Clear()
345	}
346	if x.Eq(y) {
347		return z.SetOne()
348	}
349	if x.IsInt64() && y.IsInt64() {
350		return z.SetInt64(x.Int64() / y.Int64())
351	}
352	quot := Int{}
353	udivrem(quot[:], x[:], y)
354	return z.Set(&quot)
355}
356
357func (z *Int) Rem(x, y *Int) *Int {
358	if x.Sign() > 0 {
359		if y.Sign() > 0 {
360			return z.urem(x, y)
361		}
362		return z.urem(x, new(Int).Neg(y))
363	}
364	if y.Sign() < 0 {
365		z.urem(new(Int).Neg(x), new(Int).Neg(y))
366		return z.Neg(z)
367	}
368	z.urem(new(Int).Neg(x), y)
369	return z.Neg(z)
370}
371
372func (z *Int) urem(x, y *Int) *Int {
373	if y.IsZero() {
374		panic("zero division")
375	}
376	if x.IsZero() {
377		return z.Clear()
378	}
379	if x.Eq(y) {
380		return z.Clear()
381	}
382	if x.IsInt64() && y.IsInt64() {
383		xInt64 := x.Int64()
384		yInt64 := y.Int64()
385		return z.SetInt64(xInt64 % yInt64)
386	}
387	quot := Int{}
388	rem := udivrem(quot[:], x[:], y)
389	return z.Set(&rem)
390}
391
392func (z *Int) Lt(x *Int) bool {
393	return z.Cmp(x) < 0
394}
395
396func (z *Int) Lte(x *Int) bool {
397	return z.Cmp(x) <= 0
398}
399
400func (z *Int) Gt(x *Int) bool {
401	return z.Cmp(x) > 0
402}
403
404func (z *Int) Gte(x *Int) bool {
405	return z.Cmp(x) >= 0
406}
407
408func (z *Int) Cmp(x *Int) int {
409	zneg := int8(z[3] >> 63)
410	xneg := int8(x[3] >> 63)
411	if zneg != xneg {
412		return int(xneg - zneg)
413	}
414	d0, carry := bits.Sub64(z[0], x[0], 0)
415	d1, carry := bits.Sub64(z[1], x[1], carry)
416	d2, carry := bits.Sub64(z[2], x[2], carry)
417	d3, carry := bits.Sub64(z[3], x[3], carry)
418	if carry == 1 {
419		return -1
420	}
421	if d0|d1|d2|d3 == 0 {
422		return 0
423	}
424	return 1
425}
426
427func (z *Int) Clone() *Int {
428	return &Int{z[0], z[1], z[2], z[3]}
429}
430
431func (z *Int) Or(x, y *Int) *Int {
432	z[0] = x[0] | y[0]
433	z[1] = x[1] | y[1]
434	z[2] = x[2] | y[2]
435	z[3] = x[3] | y[3]
436	return z
437}
438
439func (z *Int) And(x, y *Int) *Int {
440	z[0] = x[0] & y[0]
441	z[1] = x[1] & y[1]
442	z[2] = x[2] & y[2]
443	z[3] = x[3] & y[3]
444	return z
445}
446
447func (z *Int) Xor(x, y *Int) *Int {
448	z[0] = x[0] ^ y[0]
449	z[1] = x[1] ^ y[1]
450	z[2] = x[2] ^ y[2]
451	z[3] = x[3] ^ y[3]
452	return z
453}
454
455func (z *Int) Not(x *Int) *Int {
456	z[0] = ^x[0]
457	z[1] = ^x[1]
458	z[2] = ^x[2]
459	z[3] = ^x[3]
460	return z
461}
462
463func (z *Int) Lsh(x *Int, n uint) *Int {
464	if n == 0 {
465		return z.Set(x)
466	}
467	if n >= 256 {
468		return z.Clear()
469	}
470	// Handle exact multiples of 64 separately to avoid 64-bit shift issues
471	if n&0x3f == 0 {
472		switch n {
473		case 64:
474			z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0
475		case 128:
476			z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0
477		case 192:
478			z[3], z[2], z[1], z[0] = x[0], 0, 0, 0
479		}
480		return z
481	}
482	switch {
483	case n > 192:
484		n -= 192
485		z[3], z[2], z[1], z[0] = x[0]<<n, 0, 0, 0
486	case n > 128:
487		n -= 128
488		z[3] = (x[1] << n) | (x[0] >> (64 - n))
489		z[2] = x[0] << n
490		z[1], z[0] = 0, 0
491	case n > 64:
492		n -= 64
493		z[3] = (x[2] << n) | (x[1] >> (64 - n))
494		z[2] = (x[1] << n) | (x[0] >> (64 - n))
495		z[1] = x[0] << n
496		z[0] = 0
497	default:
498		z[3] = (x[3] << n) | (x[2] >> (64 - n))
499		z[2] = (x[2] << n) | (x[1] >> (64 - n))
500		z[1] = (x[1] << n) | (x[0] >> (64 - n))
501		z[0] = x[0] << n
502	}
503	return z
504}
505
506func (z *Int) Rsh(x *Int, n uint) *Int {
507	if n == 0 {
508		return z.Set(x)
509	}
510	if x.IsNeg() {
511		return z.negRsh(x, n)
512	}
513	return z.rsh(x, n)
514}
515
516func (z *Int) rsh(x *Int, n uint) *Int {
517	if n >= 256 {
518		return z.Clear()
519	}
520	// Handle exact multiples of 64 separately to avoid 64-bit shift issues
521	if n&0x3f == 0 {
522		switch n {
523		case 0:
524			return z.Set(x)
525		case 64:
526			z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1]
527		case 128:
528			z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2]
529		case 192:
530			z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]
531		}
532		return z
533	}
534	switch {
535	case n > 192:
536		n -= 192
537		z[3], z[2], z[1], z[0] = 0, 0, 0, x[3]>>n
538	case n > 128:
539		n -= 128
540		z[3], z[2] = 0, 0
541		z[1] = x[3] >> n
542		z[0] = (x[3] << (64 - n)) | (x[2] >> n)
543	case n > 64:
544		n -= 64
545		z[3] = 0
546		z[2] = x[3] >> n
547		z[1] = (x[3] << (64 - n)) | (x[2] >> n)
548		z[0] = (x[2] << (64 - n)) | (x[1] >> n)
549	default:
550		z[3] = x[3] >> n
551		z[2] = (x[3] << (64 - n)) | (x[2] >> n)
552		z[1] = (x[2] << (64 - n)) | (x[1] >> n)
553		z[0] = (x[1] << (64 - n)) | (x[0] >> n)
554	}
555	return z
556}
557
558func (z *Int) negRsh(x *Int, n uint) *Int {
559	if n >= 256 {
560		return z.SetAllBitsOne()
561	}
562	var v uint64 = 0xffffffffffffffff
563	// Handle exact multiples of 64 separately to avoid 64-bit shift issues
564	if n&0x3f == 0 {
565		switch n {
566		case 0:
567			return z.Set(x)
568		case 64:
569			z[3], z[2], z[1], z[0] = v, x[3], x[2], x[1]
570		case 128:
571			z[3], z[2], z[1], z[0] = v, v, x[3], x[2]
572		case 192:
573			z[3], z[2], z[1], z[0] = v, v, v, x[3]
574		}
575		return z
576	}
577	switch {
578	case n > 192:
579		n -= 192
580		z[3], z[2], z[1], z[0] = v, v, v, (v<<(64-n))|(x[3]>>n)
581	case n > 128:
582		n -= 128
583		z[3], z[2] = v, v
584		z[1] = (v << (64 - n)) | (x[3] >> n)
585		z[0] = (x[3] << (64 - n)) | (x[2] >> n)
586	case n > 64:
587		n -= 64
588		z[3] = v
589		z[2] = (v << (64 - n)) | (x[3] >> n)
590		z[1] = (x[3] << (64 - n)) | (x[2] >> n)
591		z[0] = (x[2] << (64 - n)) | (x[1] >> n)
592	default:
593		z[3] = (v << (64 - n)) | (x[3] >> n)
594		z[2] = (x[3] << (64 - n)) | (x[2] >> n)
595		z[1] = (x[2] << (64 - n)) | (x[1] >> n)
596		z[0] = (x[1] << (64 - n)) | (x[0] >> n)
597	}
598	return z
599}
600
601func (z *Int) BitLen() int {
602	switch {
603	case z[3] != 0:
604		return 192 + bits.Len64(z[3])
605	case z[2] != 0:
606		return 128 + bits.Len64(z[2])
607	case z[1] != 0:
608		return 64 + bits.Len64(z[1])
609	default:
610		return bits.Len64(z[0])
611	}
612}
613
614func (z *Int) SetBytes32(in []byte) *Int {
615	_ = in[31] // bounds check hint to compiler; see golang.org/issue/14808
616	z[3] = binary.BigEndian.Uint64(in[0:8])
617	z[2] = binary.BigEndian.Uint64(in[8:16])
618	z[1] = binary.BigEndian.Uint64(in[16:24])
619	z[0] = binary.BigEndian.Uint64(in[24:32])
620	return z
621}