OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / math / checked / checked.go
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 }