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

     1  package int256
     2  
     3  import (
     4  	"gno.land/p/demo/uint256"
     5  )
     6  
     7  func (z *Int) Add(x, y *Int) *Int {
     8  	z.initiateAbs()
     9  
    10  	neg := x.neg
    11  
    12  	if x.neg == y.neg {
    13  		// x + y == x + y
    14  		// (-x) + (-y) == -(x + y)
    15  		z.abs = z.abs.Add(x.abs, y.abs)
    16  	} else {
    17  		// x + (-y) == x - y == -(y - x)
    18  		// (-x) + y == y - x == -(x - y)
    19  		if x.abs.Cmp(y.abs) >= 0 {
    20  			z.abs = z.abs.Sub(x.abs, y.abs)
    21  		} else {
    22  			neg = !neg
    23  			z.abs = z.abs.Sub(y.abs, x.abs)
    24  		}
    25  	}
    26  	z.neg = neg // 0 has no sign
    27  	return z
    28  }
    29  
    30  // AddUint256 set z to the sum x + y, where y is a uint256, and returns z
    31  func (z *Int) AddUint256(x *Int, y *uint256.Uint) *Int {
    32  	if x.neg {
    33  		if x.abs.Gt(y) {
    34  			z.abs.Sub(x.abs, y)
    35  			z.neg = true
    36  		} else {
    37  			z.abs.Sub(y, x.abs)
    38  			z.neg = false
    39  		}
    40  	} else {
    41  		z.abs.Add(x.abs, y)
    42  		z.neg = false
    43  	}
    44  	return z
    45  }
    46  
    47  // Sets z to the sum x + y, where z and x are uint256s and y is an int256.
    48  func AddDelta(z, x *uint256.Uint, y *Int) {
    49  	if y.neg {
    50  		z.Sub(x, y.abs)
    51  	} else {
    52  		z.Add(x, y.abs)
    53  	}
    54  }
    55  
    56  // Sets z to the sum x + y, where z and x are uint256s and y is an int256.
    57  func AddDeltaOverflow(z, x *uint256.Uint, y *Int) bool {
    58  	var overflow bool
    59  	if y.neg {
    60  		_, overflow = z.SubOverflow(x, y.abs)
    61  	} else {
    62  		_, overflow = z.AddOverflow(x, y.abs)
    63  	}
    64  	return overflow
    65  }
    66  
    67  // Sub sets z to the difference x-y and returns z.
    68  func (z *Int) Sub(x, y *Int) *Int {
    69  	z.initiateAbs()
    70  
    71  	neg := x.neg
    72  	if x.neg != y.neg {
    73  		// x - (-y) == x + y
    74  		// (-x) - y == -(x + y)
    75  		z.abs = z.abs.Add(x.abs, y.abs)
    76  	} else {
    77  		// x - y == x - y == -(y - x)
    78  		// (-x) - (-y) == y - x == -(x - y)
    79  		if x.abs.Cmp(y.abs) >= 0 {
    80  			z.abs = z.abs.Sub(x.abs, y.abs)
    81  		} else {
    82  			neg = !neg
    83  			z.abs = z.abs.Sub(y.abs, x.abs)
    84  		}
    85  	}
    86  	z.neg = neg // 0 has no sign
    87  	return z
    88  }
    89  
    90  // SubUint256 set z to the difference x - y, where y is a uint256, and returns z
    91  func (z *Int) SubUint256(x *Int, y *uint256.Uint) *Int {
    92  	if x.neg {
    93  		z.abs.Add(x.abs, y)
    94  		z.neg = true
    95  	} else {
    96  		if x.abs.Lt(y) {
    97  			z.abs.Sub(y, x.abs)
    98  			z.neg = true
    99  		} else {
   100  			z.abs.Sub(x.abs, y)
   101  			z.neg = false
   102  		}
   103  	}
   104  	return z
   105  }
   106  
   107  // Mul sets z to the product x*y and returns z.
   108  func (z *Int) Mul(x, y *Int) *Int {
   109  	z.initiateAbs()
   110  
   111  	z.abs = z.abs.Mul(x.abs, y.abs)
   112  	z.neg = x.neg != y.neg // 0 has no sign
   113  	return z
   114  }
   115  
   116  // MulUint256 sets z to the product x*y, where y is a uint256, and returns z
   117  func (z *Int) MulUint256(x *Int, y *uint256.Uint) *Int {
   118  	z.abs.Mul(x.abs, y)
   119  	if z.abs.IsZero() {
   120  		z.neg = false
   121  	} else {
   122  		z.neg = x.neg
   123  	}
   124  	return z
   125  }
   126  
   127  // Div sets z to the quotient x/y for y != 0 and returns z.
   128  func (z *Int) Div(x, y *Int) *Int {
   129  	z.initiateAbs()
   130  
   131  	z.abs.Div(x.abs, y.abs)
   132  	if x.neg == y.neg {
   133  		z.neg = false
   134  	} else {
   135  		z.neg = true
   136  	}
   137  	return z
   138  }
   139  
   140  // DivUint256 sets z to the quotient x/y, where y is a uint256, and returns z
   141  // If y == 0, z is set to 0
   142  func (z *Int) DivUint256(x *Int, y *uint256.Uint) *Int {
   143  	z.abs.Div(x.abs, y)
   144  	if z.abs.IsZero() {
   145  		z.neg = false
   146  	} else {
   147  		z.neg = x.neg
   148  	}
   149  	return z
   150  }
   151  
   152  // Quo sets z to the quotient x/y for y != 0 and returns z.
   153  // If y == 0, a division-by-zero run-time panic occurs.
   154  // OBS: differs from mempooler int256, we need to panic manually if y == 0
   155  // Quo implements truncated division (like Go); see QuoRem for more details.
   156  func (z *Int) Quo(x, y *Int) *Int {
   157  	if y.IsZero() {
   158  		panic("division by zero")
   159  	}
   160  
   161  	z.initiateAbs()
   162  
   163  	z.abs = z.abs.Div(x.abs, y.abs)
   164  	z.neg = !(z.abs.IsZero()) && x.neg != y.neg // 0 has no sign
   165  	return z
   166  }
   167  
   168  // Rem sets z to the remainder x%y for y != 0 and returns z.
   169  // If y == 0, a division-by-zero run-time panic occurs.
   170  // OBS: differs from mempooler int256, we need to panic manually if y == 0
   171  // Rem implements truncated modulus (like Go); see QuoRem for more details.
   172  func (z *Int) Rem(x, y *Int) *Int {
   173  	if y.IsZero() {
   174  		panic("division by zero")
   175  	}
   176  
   177  	z.initiateAbs()
   178  
   179  	z.abs.Mod(x.abs, y.abs)
   180  	z.neg = z.abs.Sign() > 0 && x.neg // 0 has no sign
   181  	return z
   182  }
   183  
   184  // Mod sets z to the modulus x%y for y != 0 and returns z.
   185  // If y == 0, z is set to 0 (OBS: differs from the big.Int)
   186  func (z *Int) Mod(x, y *Int) *Int {
   187  	if x.neg {
   188  		z.abs.Div(x.abs, y.abs)
   189  		z.abs.Add(z.abs, one)
   190  		z.abs.Mul(z.abs, y.abs)
   191  		z.abs.Sub(z.abs, x.abs)
   192  		z.abs.Mod(z.abs, y.abs)
   193  	} else {
   194  		z.abs.Mod(x.abs, y.abs)
   195  	}
   196  	z.neg = false
   197  	return z
   198  }