github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/common/number/int.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package number
    13  
    14  import (
    15  	"math/big"
    16  
    17  	"github.com/Sberex/go-sberex/common"
    18  )
    19  
    20  var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
    21  var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
    22  var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
    23  
    24  func limitUnsigned256(x *Number) *Number {
    25  	x.num.And(x.num, tt256m1)
    26  	return x
    27  }
    28  
    29  func limitSigned256(x *Number) *Number {
    30  	if x.num.Cmp(tt255) < 0 {
    31  		return x
    32  	} else {
    33  		x.num.Sub(x.num, tt256)
    34  		return x
    35  	}
    36  }
    37  
    38  // Number function
    39  type Initialiser func(n int64) *Number
    40  
    41  // A Number represents a generic integer with a bounding function limiter. Limit is called after each operations
    42  // to give "fake" bounded integers. New types of Number can be created through NewInitialiser returning a lambda
    43  // with the new Initialiser.
    44  type Number struct {
    45  	num   *big.Int
    46  	limit func(n *Number) *Number
    47  }
    48  
    49  // Returns a new initialiser for a new *Number without having to expose certain fields
    50  func NewInitialiser(limiter func(*Number) *Number) Initialiser {
    51  	return func(n int64) *Number {
    52  		return &Number{big.NewInt(n), limiter}
    53  	}
    54  }
    55  
    56  // Return a Number with a UNSIGNED limiter up to 256 bits
    57  func Uint256(n int64) *Number {
    58  	return &Number{big.NewInt(n), limitUnsigned256}
    59  }
    60  
    61  // Return a Number with a SIGNED limiter up to 256 bits
    62  func Int256(n int64) *Number {
    63  	return &Number{big.NewInt(n), limitSigned256}
    64  }
    65  
    66  // Returns a Number with a SIGNED unlimited size
    67  func Big(n int64) *Number {
    68  	return &Number{big.NewInt(n), func(x *Number) *Number { return x }}
    69  }
    70  
    71  // Sets i to sum of x+y
    72  func (i *Number) Add(x, y *Number) *Number {
    73  	i.num.Add(x.num, y.num)
    74  	return i.limit(i)
    75  }
    76  
    77  // Sets i to difference of x-y
    78  func (i *Number) Sub(x, y *Number) *Number {
    79  	i.num.Sub(x.num, y.num)
    80  	return i.limit(i)
    81  }
    82  
    83  // Sets i to product of x*y
    84  func (i *Number) Mul(x, y *Number) *Number {
    85  	i.num.Mul(x.num, y.num)
    86  	return i.limit(i)
    87  }
    88  
    89  // Sets i to the quotient prodject of x/y
    90  func (i *Number) Div(x, y *Number) *Number {
    91  	i.num.Div(x.num, y.num)
    92  	return i.limit(i)
    93  }
    94  
    95  // Sets i to x % y
    96  func (i *Number) Mod(x, y *Number) *Number {
    97  	i.num.Mod(x.num, y.num)
    98  	return i.limit(i)
    99  }
   100  
   101  // Sets i to x << s
   102  func (i *Number) Lsh(x *Number, s uint) *Number {
   103  	i.num.Lsh(x.num, s)
   104  	return i.limit(i)
   105  }
   106  
   107  // Sets i to x^y
   108  func (i *Number) Pow(x, y *Number) *Number {
   109  	i.num.Exp(x.num, y.num, big.NewInt(0))
   110  	return i.limit(i)
   111  }
   112  
   113  // Setters
   114  
   115  // Set x to i
   116  func (i *Number) Set(x *Number) *Number {
   117  	i.num.Set(x.num)
   118  	return i.limit(i)
   119  }
   120  
   121  // Set x bytes to i
   122  func (i *Number) SetBytes(x []byte) *Number {
   123  	i.num.SetBytes(x)
   124  	return i.limit(i)
   125  }
   126  
   127  // Cmp compares x and y and returns:
   128  //
   129  //     -1 if x <  y
   130  //     0 if x == y
   131  //     +1 if x >  y
   132  func (i *Number) Cmp(x *Number) int {
   133  	return i.num.Cmp(x.num)
   134  }
   135  
   136  // Getters
   137  
   138  // Returns the string representation of i
   139  func (i *Number) String() string {
   140  	return i.num.String()
   141  }
   142  
   143  // Returns the byte representation of i
   144  func (i *Number) Bytes() []byte {
   145  	return i.num.Bytes()
   146  }
   147  
   148  // Uint64 returns the Uint64 representation of x. If x cannot be represented in an int64, the result is undefined.
   149  func (i *Number) Uint64() uint64 {
   150  	return i.num.Uint64()
   151  }
   152  
   153  // Int64 returns the int64 representation of x. If x cannot be represented in an int64, the result is undefined.
   154  func (i *Number) Int64() int64 {
   155  	return i.num.Int64()
   156  }
   157  
   158  // Returns the signed version of i
   159  func (i *Number) Int256() *Number {
   160  	return Int(0).Set(i)
   161  }
   162  
   163  // Returns the unsigned version of i
   164  func (i *Number) Uint256() *Number {
   165  	return Uint(0).Set(i)
   166  }
   167  
   168  // Returns the index of the first bit that's set to 1
   169  func (i *Number) FirstBitSet() int {
   170  	for j := 0; j < i.num.BitLen(); j++ {
   171  		if i.num.Bit(j) > 0 {
   172  			return j
   173  		}
   174  	}
   175  
   176  	return i.num.BitLen()
   177  }
   178  
   179  // Variables
   180  
   181  var (
   182  	Zero       = Uint(0)
   183  	One        = Uint(1)
   184  	Two        = Uint(2)
   185  	MaxUint256 = Uint(0).SetBytes(common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
   186  
   187  	MinOne = Int(-1)
   188  
   189  	// "typedefs"
   190  	Uint = Uint256
   191  	Int  = Int256
   192  )