int256.gno

3.24 Kb ยท 129 lines
  1package int256
  2
  3import (
  4	"errors"
  5
  6	"gno.land/p/demo/uint256"
  7)
  8
  9var (
 10	int1  = NewInt(1)
 11	uint0 = uint256.NewUint(0)
 12	uint1 = uint256.NewUint(1)
 13)
 14
 15type Int struct {
 16	value uint256.Uint
 17}
 18
 19// New creates and returns a new Int initialized to zero.
 20func New() *Int {
 21	return &Int{}
 22}
 23
 24// NewInt allocates and returns a new Int set to the value of the provided int64.
 25func NewInt(x int64) *Int {
 26	return New().SetInt64(x)
 27}
 28
 29// Zero returns a new Int initialized to 0.
 30//
 31// This function is useful for creating a starting point for calculations or
 32// when an explicit zero value is needed.
 33func Zero() *Int { return &Int{} }
 34
 35// One returns a new Int initialized to one.
 36//
 37// This function is convenient for operations that require a unit value,
 38// such as incrementing or serving as an identity element in multiplication.
 39func One() *Int {
 40	return &Int{
 41		value: *uint256.NewUint(1),
 42	}
 43}
 44
 45// Sign determines the sign of the Int.
 46//
 47// It returns -1 for negative numbers, 0 for zero, and +1 for positive numbers.
 48func (z *Int) Sign() int {
 49	if z == nil || z.IsZero() {
 50		return 0
 51	}
 52	// Right shift the value by 255 bits to check the sign bit.
 53	// In two's complement representation, the most significant bit (MSB) is the sign bit.
 54	// If the MSB is 0, the number is positive; if it is 1, the number is negative.
 55	//
 56	// Example:
 57	// Original value:  1 0 1 0 ... 0 1  (256 bits)
 58	// After Rsh 255:   0 0 0 0 ... 0 1  (1 bit)
 59	//
 60	// This approach is highly efficient as it avoids the need for comparisons
 61	// or arithmetic operations on the full 256-bit number. Instead it reduces
 62	// the problem to checking a single bit.
 63	//
 64	// Additionally, this method will work correctly for all values,
 65	// including the minimum possible negative number (which in two's complement
 66	// doesn't have a positive counterpart in the same bit range).
 67	var temp uint256.Uint
 68	if temp.Rsh(&z.value, 255).IsZero() {
 69		return 1
 70	}
 71	return -1
 72}
 73
 74// FromDecimal creates a new Int from a decimal string representation.
 75// It handles both positive and negative values.
 76//
 77// This function is useful for parsing user input or reading numeric data
 78// from text-based formats.
 79func FromDecimal(s string) (*Int, error) {
 80	return New().SetString(s)
 81}
 82
 83// MustFromDecimal is similar to FromDecimal but panics if the input string
 84// is not a valid decimal representation.
 85func MustFromDecimal(s string) *Int {
 86	z, err := FromDecimal(s)
 87	if err != nil {
 88		panic(err)
 89	}
 90	return z
 91}
 92
 93// SetString sets the Int to the value represented by the input string.
 94// This method supports decimal string representations of integers and handles
 95// both positive and negative values.
 96func (z *Int) SetString(s string) (*Int, error) {
 97	if len(s) == 0 {
 98		return nil, errors.New("cannot set int256 from empty string")
 99	}
100
101	// Check for negative sign
102	neg := s[0] == '-'
103	if neg || s[0] == '+' {
104		s = s[1:]
105	}
106
107	// Convert string to uint256
108	temp, err := uint256.FromDecimal(s)
109	if err != nil {
110		return nil, err
111	}
112
113	// If negative, negate the uint256 value
114	if neg {
115		temp.Neg(temp)
116	}
117
118	z.value.Set(temp)
119	return z, nil
120}
121
122// FromUint256 sets the Int to the value of the provided Uint256.
123//
124// This method allows for conversion from unsigned 256-bit integers
125// to signed integers.
126func (z *Int) FromUint256(v *uint256.Uint) *Int {
127	z.value.Set(v)
128	return z
129}