github.com/ontio/ontology@v1.14.4/vm/neovm/types/int_value.go (about)

     1  /*
     2   * Copyright (C) 2018 The ontology Authors
     3   * This file is part of The ontology library.
     4   *
     5   * The ontology is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU Lesser General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * The ontology is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU Lesser General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU Lesser General Public License
    16   * along with The ontology.  If not, see <http://www.gnu.org/licenses/>.
    17   */
    18  
    19  package types
    20  
    21  import (
    22  	"math"
    23  	"math/big"
    24  
    25  	"github.com/JohnCGriffin/overflow"
    26  	"github.com/ontio/ontology/common"
    27  	"github.com/ontio/ontology/vm/neovm/constants"
    28  	"github.com/ontio/ontology/vm/neovm/errors"
    29  )
    30  
    31  type IntValue struct {
    32  	isbig   bool
    33  	integer int64
    34  	bigint  *big.Int
    35  }
    36  
    37  func (self IntValue) Rsh(other IntValue) (result IntValue, err error) {
    38  	var val uint64
    39  	if !other.isbig {
    40  		if other.integer < 0 {
    41  			err = errors.ERR_SHIFT_BY_NEG
    42  			return
    43  		}
    44  		val = uint64(other.integer)
    45  	} else {
    46  		if !other.bigint.IsUint64() {
    47  			return IntValue{}, errors.ERR_SHIFT_BY_NEG
    48  		}
    49  		val = other.bigint.Uint64()
    50  	}
    51  
    52  	if val > constants.MAX_INT_SIZE*8 {
    53  		// IntValue is enforced to not exceed this size, so return 0 directly
    54  		// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)  reference from big.Int
    55  		// (-x) >> s == -(0 + 1) == -1
    56  		if self.Sign() < 0 {
    57  			result = IntValFromInt(-1)
    58  		}
    59  		return
    60  	}
    61  
    62  	left := big.NewInt(self.integer)
    63  	if self.isbig {
    64  		left.Set(self.bigint)
    65  	}
    66  
    67  	left.Rsh(left, uint(val))
    68  
    69  	return IntValFromBigInt(left)
    70  }
    71  
    72  func (self IntValue) Lsh(other IntValue) (result IntValue, err error) {
    73  	var val uint64
    74  	if !other.isbig {
    75  		if other.integer < 0 {
    76  			err = errors.ERR_SHIFT_BY_NEG
    77  			return
    78  		}
    79  		val = uint64(other.integer)
    80  	} else {
    81  		if !other.bigint.IsUint64() {
    82  			return IntValue{}, errors.ERR_SHIFT_BY_NEG
    83  		}
    84  		val = other.bigint.Uint64()
    85  	}
    86  
    87  	if val > constants.MAX_INT_SIZE*8 {
    88  		err = errors.ERR_OVER_MAX_BIGINTEGER_SIZE
    89  		return
    90  	}
    91  
    92  	left := big.NewInt(self.integer)
    93  	if self.isbig {
    94  		left.Set(self.bigint)
    95  	}
    96  
    97  	left.Lsh(left, uint(val))
    98  
    99  	return IntValFromBigInt(left)
   100  }
   101  
   102  func IntValFromBigInt(val *big.Int) (result IntValue, err error) {
   103  	if val == nil {
   104  		err = errors.ERR_BAD_VALUE
   105  		return
   106  	}
   107  	// todo : check compatibility
   108  	if len(val.Bytes()) > constants.MAX_INT_SIZE {
   109  		err = errors.ERR_OVER_MAX_BIGINTEGER_SIZE
   110  	}
   111  
   112  	if val.IsInt64() {
   113  		result.isbig = false
   114  		result.integer = val.Int64()
   115  	} else {
   116  		result.isbig = true
   117  		result.bigint = val
   118  	}
   119  
   120  	return
   121  }
   122  
   123  func IntValFromNeoBytes(val []byte) (IntValue, error) {
   124  	value := common.BigIntFromNeoBytes(val)
   125  	return IntValFromBigInt(value)
   126  }
   127  
   128  func (self *IntValue) ToNeoBytes() []byte {
   129  	val := self.bigint
   130  	if !self.isbig {
   131  		val = big.NewInt(self.integer)
   132  	}
   133  	value := common.BigIntToNeoBytes(val)
   134  	return value
   135  }
   136  
   137  func IntValFromInt(val int64) IntValue {
   138  	return IntValue{isbig: false, integer: val}
   139  }
   140  
   141  func (self *IntValue) IsZero() bool {
   142  	if self.isbig {
   143  		return self.bigint.Sign() == 0
   144  	} else {
   145  		return self.integer == 0
   146  	}
   147  }
   148  
   149  func (self *IntValue) Sign() int {
   150  	if self.isbig {
   151  		return self.bigint.Sign()
   152  	} else {
   153  		if self.integer < 0 {
   154  			return -1
   155  		} else if self.integer == 0 {
   156  			return 0
   157  		} else {
   158  			return 1
   159  		}
   160  	}
   161  }
   162  
   163  func (self IntValue) Max(other IntValue) (IntValue, error) {
   164  	return self.intOp(other, func(a, b int64) (int64, bool) {
   165  		if a < b {
   166  			return b, true
   167  		}
   168  		return a, true
   169  	}, func(a, b *big.Int) (IntValue, error) {
   170  		result := new(big.Int)
   171  		c := a.Cmp(b)
   172  		if c <= 0 {
   173  			result.Set(b)
   174  		} else {
   175  			result.Set(a)
   176  		}
   177  		return IntValFromBigInt(result)
   178  	})
   179  }
   180  
   181  func (self IntValue) Min(other IntValue) (IntValue, error) {
   182  	return self.intOp(other, func(a, b int64) (int64, bool) {
   183  		if a < b {
   184  			return a, true
   185  		}
   186  		return b, true
   187  	}, func(a, b *big.Int) (IntValue, error) {
   188  		result := new(big.Int)
   189  		c := a.Cmp(b)
   190  		if c <= 0 {
   191  			result.Set(a)
   192  		} else {
   193  			result.Set(b)
   194  		}
   195  		return IntValFromBigInt(result)
   196  	})
   197  }
   198  
   199  func (self IntValue) Xor(other IntValue) (IntValue, error) {
   200  	return self.intOp(other, func(a, b int64) (int64, bool) {
   201  		return a ^ b, true
   202  	}, func(a, b *big.Int) (IntValue, error) {
   203  		return IntValFromBigInt(new(big.Int).Xor(a, b))
   204  	})
   205  }
   206  
   207  func (self IntValue) And(other IntValue) (IntValue, error) {
   208  	return self.intOp(other, func(a, b int64) (int64, bool) {
   209  		return a & b, true
   210  	}, func(a, b *big.Int) (IntValue, error) {
   211  		return IntValFromBigInt(new(big.Int).And(a, b))
   212  	})
   213  }
   214  
   215  func (self IntValue) Or(other IntValue) (IntValue, error) {
   216  	return self.intOp(other, func(a, b int64) (int64, bool) {
   217  		return a | b, true
   218  	}, func(a, b *big.Int) (IntValue, error) {
   219  		return IntValFromBigInt(new(big.Int).Or(a, b))
   220  	})
   221  }
   222  
   223  func (self IntValue) Cmp(other IntValue) int {
   224  	if !self.isbig && !other.isbig {
   225  		if self.integer < other.integer {
   226  			return -1
   227  		} else if self.integer == other.integer {
   228  			return 0
   229  		} else {
   230  			return 1
   231  		}
   232  	}
   233  	var left, right *big.Int
   234  	if !self.isbig {
   235  		left = big.NewInt(self.integer)
   236  	} else {
   237  		left = self.bigint
   238  	}
   239  	if !other.isbig {
   240  		right = big.NewInt(other.integer)
   241  	} else {
   242  		right = other.bigint
   243  	}
   244  
   245  	return left.Cmp(right)
   246  }
   247  
   248  func (self IntValue) Not() (val IntValue) {
   249  	if self.isbig {
   250  		val.isbig = true
   251  		val.bigint = big.NewInt(0)
   252  		val.bigint.Not(self.bigint)
   253  	} else {
   254  		val.integer = ^self.integer
   255  	}
   256  	return
   257  }
   258  
   259  func (self IntValue) Abs() (val IntValue) {
   260  	if self.isbig {
   261  		val.isbig = true
   262  		val.bigint = big.NewInt(0)
   263  		val.bigint.Abs(self.bigint)
   264  	} else {
   265  		if self.integer == math.MinInt64 {
   266  			val.isbig = true
   267  			val.bigint = big.NewInt(self.integer)
   268  			val.bigint.Abs(val.bigint)
   269  		} else if self.integer < 0 {
   270  			val.integer = -self.integer
   271  		} else {
   272  			val.integer = self.integer
   273  		}
   274  	}
   275  	return
   276  }
   277  
   278  // todo: check negative value with big.Int
   279  func (self IntValue) Mod(other IntValue) (IntValue, error) {
   280  	if other.IsZero() {
   281  		return IntValue{}, errors.ERR_DIV_MOD_BY_ZERO
   282  	}
   283  	return self.intOp(other, func(a, b int64) (int64, bool) {
   284  		return a % b, true
   285  	}, func(a, b *big.Int) (IntValue, error) {
   286  		return IntValFromBigInt(new(big.Int).Rem(a, b))
   287  	})
   288  }
   289  
   290  // todo: check negative value with big.Int
   291  func (self IntValue) Div(other IntValue) (IntValue, error) {
   292  	if other.IsZero() {
   293  		return IntValue{}, errors.ERR_DIV_MOD_BY_ZERO
   294  	}
   295  	return self.intOp(other, func(a, b int64) (int64, bool) {
   296  		return a / b, true
   297  	}, func(a, b *big.Int) (IntValue, error) {
   298  		return IntValFromBigInt(new(big.Int).Quo(a, b))
   299  	})
   300  }
   301  
   302  func (self IntValue) Mul(other IntValue) (IntValue, error) {
   303  	return self.intOp(other, overflow.Mul64, func(a, b *big.Int) (IntValue, error) {
   304  		return IntValFromBigInt(new(big.Int).Mul(a, b))
   305  	})
   306  }
   307  
   308  func (self IntValue) Add(other IntValue) (IntValue, error) {
   309  	return self.intOp(other, overflow.Add64, func(a, b *big.Int) (IntValue, error) {
   310  		return IntValFromBigInt(new(big.Int).Add(a, b))
   311  	})
   312  }
   313  
   314  func (self IntValue) Sub(other IntValue) (IntValue, error) {
   315  	return self.intOp(other, overflow.Sub64, func(a, b *big.Int) (IntValue, error) {
   316  		return IntValFromBigInt(new(big.Int).Sub(a, b))
   317  	})
   318  }
   319  
   320  type overflowFn func(a, b int64) (result int64, ok bool)
   321  type bigintFn func(a, b *big.Int) (IntValue, error)
   322  
   323  func (self IntValue) intOp(other IntValue, littleintFunc overflowFn, bigintFunc bigintFn) (IntValue, error) {
   324  	if !self.isbig && !other.isbig {
   325  		val, ok := littleintFunc(self.integer, other.integer)
   326  		if ok {
   327  			return IntValFromInt(val), nil
   328  		}
   329  	}
   330  	var left, right *big.Int
   331  	if !self.isbig {
   332  		left = big.NewInt(self.integer)
   333  	} else {
   334  		left = self.bigint
   335  	}
   336  	if !other.isbig {
   337  		right = big.NewInt(other.integer)
   338  	} else {
   339  		right = other.bigint
   340  	}
   341  
   342  	return bigintFunc(left, right)
   343  }