github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/math/checked/checked.go (about) 1 /* 2 Package checked implements basic arithmetic operations 3 with underflow and overflow checks. 4 */ 5 package checked 6 7 import ( 8 "errors" 9 "math" 10 "math/big" 11 12 "github.com/holiman/uint256" 13 ) 14 15 var ErrOverflow = errors.New("arithmetic overflow") 16 17 // AddInt64 returns a + b 18 // with an integer overflow check. 19 func AddInt64(a, b int64) (sum int64, ok bool) { 20 if (b > 0 && a > math.MaxInt64-b) || 21 (b < 0 && a < math.MinInt64-b) { 22 return 0, false 23 } 24 return a + b, true 25 } 26 27 // SubInt64 returns a - b 28 // with an integer overflow check. 29 func SubInt64(a, b int64) (diff int64, ok bool) { 30 if (b > 0 && a < math.MinInt64+b) || 31 (b < 0 && a > math.MaxInt64+b) { 32 return 0, false 33 } 34 return a - b, true 35 } 36 37 // MulInt64 returns a * b 38 // with an integer overflow check. 39 func MulInt64(a, b int64) (product int64, ok bool) { 40 if (a > 0 && b > 0 && a > math.MaxInt64/b) || 41 (a > 0 && b <= 0 && b < math.MinInt64/a) || 42 (a <= 0 && b > 0 && a < math.MinInt64/b) || 43 (a < 0 && b <= 0 && b < math.MaxInt64/a) { 44 return 0, false 45 } 46 return a * b, true 47 } 48 49 // DivInt64 returns a / b 50 // with an integer overflow check. 51 func DivInt64(a, b int64) (quotient int64, ok bool) { 52 if b == 0 || (a == math.MinInt64 && b == -1) { 53 return 0, false 54 } 55 return a / b, true 56 } 57 58 // ModInt64 returns a % b 59 // with an integer overflow check. 60 func ModInt64(a, b int64) (remainder int64, ok bool) { 61 if b == 0 || (a == math.MinInt64 && b == -1) { 62 return 0, false 63 } 64 return a % b, true 65 } 66 67 // NegateInt64 returns -a 68 // with an integer overflow check. 69 func NegateInt64(a int64) (negated int64, ok bool) { 70 if a == math.MinInt64 { 71 return 0, false 72 } 73 return -a, true 74 } 75 76 // LshiftInt64 returns a << b 77 // with an integer overflow check. 78 func LshiftInt64(a, b int64) (result int64, ok bool) { 79 if b < 0 || b >= 64 { 80 return 0, false 81 } 82 if (a >= 0 && a > math.MaxInt64>>uint(b)) || (a < 0 && a < math.MinInt64>>uint(b)) { 83 return 0, false 84 } 85 return a << uint(b), true 86 } 87 88 // AddInt32 returns a + b 89 // with an integer overflow check. 90 func AddInt32(a, b int32) (sum int32, ok bool) { 91 if (b > 0 && a > math.MaxInt32-b) || 92 (b < 0 && a < math.MinInt32-b) { 93 return 0, false 94 } 95 return a + b, true 96 } 97 98 // SubInt32 returns a - b 99 // with an integer overflow check. 100 func SubInt32(a, b int32) (diff int32, ok bool) { 101 if (b > 0 && a < math.MinInt32+b) || 102 (b < 0 && a > math.MaxInt32+b) { 103 return 0, false 104 } 105 return a - b, true 106 } 107 108 // MulInt32 returns a * b 109 // with an integer overflow check. 110 func MulInt32(a, b int32) (product int32, ok bool) { 111 if (a > 0 && b > 0 && a > math.MaxInt32/b) || 112 (a > 0 && b <= 0 && b < math.MinInt32/a) || 113 (a <= 0 && b > 0 && a < math.MinInt32/b) || 114 (a < 0 && b <= 0 && b < math.MaxInt32/a) { 115 return 0, false 116 } 117 return a * b, true 118 } 119 120 // DivInt32 returns a / b 121 // with an integer overflow check. 122 func DivInt32(a, b int32) (quotient int32, ok bool) { 123 if b == 0 || (a == math.MinInt32 && b == -1) { 124 return 0, false 125 } 126 return a / b, true 127 } 128 129 // ModInt32 returns a % b 130 // with an integer overflow check. 131 func ModInt32(a, b int32) (remainder int32, ok bool) { 132 if b == 0 || (a == math.MinInt32 && b == -1) { 133 return 0, false 134 } 135 return a % b, true 136 } 137 138 // NegateInt32 returns -a 139 // with an integer overflow check. 140 func NegateInt32(a int32) (negated int32, ok bool) { 141 if a == math.MinInt32 { 142 return 0, false 143 } 144 return -a, true 145 } 146 147 // LshiftInt32 returns a << b 148 // with an integer overflow check. 149 func LshiftInt32(a, b int32) (result int32, ok bool) { 150 if b < 0 || b >= 32 { 151 return 0, false 152 } 153 if (a >= 0 && a > math.MaxInt32>>uint(b)) || (a < 0 && a < math.MinInt32>>uint(b)) { 154 return 0, false 155 } 156 return a << uint(b), true 157 } 158 159 // AddUint64 returns a + b 160 // with an integer overflow check. 161 func AddUint64(a, b uint64) (sum uint64, ok bool) { 162 if math.MaxUint64-a < b { 163 return 0, false 164 } 165 return a + b, true 166 } 167 168 // SubUint64 returns a - b 169 // with an integer overflow check. 170 func SubUint64(a, b uint64) (diff uint64, ok bool) { 171 if a < b { 172 return 0, false 173 } 174 return a - b, true 175 } 176 177 // MulUint64 returns a * b 178 // with an integer overflow check. 179 func MulUint64(a, b uint64) (product uint64, ok bool) { 180 if b > 0 && a > math.MaxUint64/b { 181 return 0, false 182 } 183 return a * b, true 184 } 185 186 // DivUint64 returns a / b 187 // with an integer overflow check. 188 func DivUint64(a, b uint64) (quotient uint64, ok bool) { 189 if b == 0 { 190 return 0, false 191 } 192 return a / b, true 193 } 194 195 // ModUint64 returns a % b 196 // with an integer overflow check. 197 func ModUint64(a, b uint64) (remainder uint64, ok bool) { 198 if b == 0 { 199 return 0, false 200 } 201 return a % b, true 202 } 203 204 // LshiftUint64 returns a << b 205 // with an integer overflow check. 206 func LshiftUint64(a, b uint64) (result uint64, ok bool) { 207 if b >= 64 { 208 return 0, false 209 } 210 if a > math.MaxUint64>>uint(b) { 211 return 0, false 212 } 213 return a << uint(b), true 214 } 215 216 // AddUint32 returns a + b 217 // with an integer overflow check. 218 func AddUint32(a, b uint32) (sum uint32, ok bool) { 219 if math.MaxUint32-a < b { 220 return 0, false 221 } 222 return a + b, true 223 } 224 225 // SubUint32 returns a - b 226 // with an integer overflow check. 227 func SubUint32(a, b uint32) (diff uint32, ok bool) { 228 if a < b { 229 return 0, false 230 } 231 return a - b, true 232 } 233 234 // MulUint32 returns a * b 235 // with an integer overflow check. 236 func MulUint32(a, b uint32) (product uint32, ok bool) { 237 if b > 0 && a > math.MaxUint32/b { 238 return 0, false 239 } 240 return a * b, true 241 } 242 243 // DivUint32 returns a / b 244 // with an integer overflow check. 245 func DivUint32(a, b uint32) (quotient uint32, ok bool) { 246 if b == 0 { 247 return 0, false 248 } 249 return a / b, true 250 } 251 252 // ModUint32 returns a % b 253 // with an integer overflow check. 254 func ModUint32(a, b uint32) (remainder uint32, ok bool) { 255 if b == 0 { 256 return 0, false 257 } 258 return a % b, true 259 } 260 261 // LshiftUint32 returns a << b 262 // with an integer overflow check. 263 func LshiftUint32(a, b uint32) (result uint32, ok bool) { 264 if b >= 32 { 265 return 0, false 266 } 267 if a > math.MaxUint32>>uint(b) { 268 return 0, false 269 } 270 return a << uint(b), true 271 } 272 273 // NewUInt256 returns uint256 274 // with an integer overflow check. 275 func NewUInt256(a string) (num *uint256.Int, ok bool) { 276 bigIntNum, ok := new(big.Int).SetString(a, 10) 277 if !ok { 278 return nil, false 279 } 280 281 uint256Num, overflow := uint256.FromBig(bigIntNum) 282 if overflow { 283 return nil, false 284 } 285 286 return uint256Num, true 287 }