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