github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/uint256/cmp.gno (about)

     1  // cmp (or, comparisons) includes methods for comparing Uint instances.
     2  // These comparison functions cover a range of operations including equality checks, less than/greater than
     3  // evaluations, and specialized comparisons such as signed greater than. These are fundamental for logical
     4  // decision making based on Uint values.
     5  package uint256
     6  
     7  import (
     8  	"math/bits"
     9  )
    10  
    11  // Cmp compares z and x and returns:
    12  //
    13  //	-1 if z <  x
    14  //	 0 if z == x
    15  //	+1 if z >  x
    16  func (z *Uint) Cmp(x *Uint) (r int) {
    17  	// z < x <=> z - x < 0 i.e. when subtraction overflows.
    18  	d0, carry := bits.Sub64(z.arr[0], x.arr[0], 0)
    19  	d1, carry := bits.Sub64(z.arr[1], x.arr[1], carry)
    20  	d2, carry := bits.Sub64(z.arr[2], x.arr[2], carry)
    21  	d3, carry := bits.Sub64(z.arr[3], x.arr[3], carry)
    22  	if carry == 1 {
    23  		return -1
    24  	}
    25  	if d0|d1|d2|d3 == 0 {
    26  		return 0
    27  	}
    28  	return 1
    29  }
    30  
    31  // IsZero returns true if z == 0
    32  func (z *Uint) IsZero() bool {
    33  	return (z.arr[0] | z.arr[1] | z.arr[2] | z.arr[3]) == 0
    34  }
    35  
    36  // Sign returns:
    37  //
    38  //	-1 if z <  0
    39  //	 0 if z == 0
    40  //	+1 if z >  0
    41  //
    42  // Where z is interpreted as a two's complement signed number
    43  func (z *Uint) Sign() int {
    44  	if z.IsZero() {
    45  		return 0
    46  	}
    47  	if z.arr[3] < 0x8000000000000000 {
    48  		return 1
    49  	}
    50  	return -1
    51  }
    52  
    53  // LtUint64 returns true if z is smaller than n
    54  func (z *Uint) LtUint64(n uint64) bool {
    55  	return z.arr[0] < n && (z.arr[1]|z.arr[2]|z.arr[3]) == 0
    56  }
    57  
    58  // GtUint64 returns true if z is larger than n
    59  func (z *Uint) GtUint64(n uint64) bool {
    60  	return z.arr[0] > n || (z.arr[1]|z.arr[2]|z.arr[3]) != 0
    61  }
    62  
    63  // Lt returns true if z < x
    64  func (z *Uint) Lt(x *Uint) bool {
    65  	// z < x <=> z - x < 0 i.e. when subtraction overflows.
    66  	_, carry := bits.Sub64(z.arr[0], x.arr[0], 0)
    67  	_, carry = bits.Sub64(z.arr[1], x.arr[1], carry)
    68  	_, carry = bits.Sub64(z.arr[2], x.arr[2], carry)
    69  	_, carry = bits.Sub64(z.arr[3], x.arr[3], carry)
    70  
    71  	return carry != 0
    72  }
    73  
    74  // Gt returns true if z > x
    75  func (z *Uint) Gt(x *Uint) bool {
    76  	return x.Lt(z)
    77  }
    78  
    79  // Lte returns true if z <= x
    80  func (z *Uint) Lte(x *Uint) bool {
    81  	cond1 := z.Lt(x)
    82  	cond2 := z.Eq(x)
    83  
    84  	if cond1 || cond2 {
    85  		return true
    86  	}
    87  	return false
    88  }
    89  
    90  // Gte returns true if z >= x
    91  func (z *Uint) Gte(x *Uint) bool {
    92  	cond1 := z.Gt(x)
    93  	cond2 := z.Eq(x)
    94  
    95  	if cond1 || cond2 {
    96  		return true
    97  	}
    98  	return false
    99  }
   100  
   101  // Eq returns true if z == x
   102  func (z *Uint) Eq(x *Uint) bool {
   103  	return (z.arr[0] == x.arr[0]) && (z.arr[1] == x.arr[1]) && (z.arr[2] == x.arr[2]) && (z.arr[3] == x.arr[3])
   104  }
   105  
   106  // Neq returns true if z != x
   107  func (z *Uint) Neq(x *Uint) bool {
   108  	return !z.Eq(x)
   109  }
   110  
   111  // Sgt interprets z and x as signed integers, and returns
   112  // true if z > x
   113  func (z *Uint) Sgt(x *Uint) bool {
   114  	zSign := z.Sign()
   115  	xSign := x.Sign()
   116  
   117  	switch {
   118  	case zSign >= 0 && xSign < 0:
   119  		return true
   120  	case zSign < 0 && xSign >= 0:
   121  		return false
   122  	default:
   123  		return z.Gt(x)
   124  	}
   125  }