aboutsummaryrefslogtreecommitdiffstats
path: root/common/math
diff options
context:
space:
mode:
Diffstat (limited to 'common/math')
-rw-r--r--common/math/integer.go25
-rw-r--r--common/math/integer_test.go50
2 files changed, 75 insertions, 0 deletions
diff --git a/common/math/integer.go b/common/math/integer.go
new file mode 100644
index 000000000..8162b1985
--- /dev/null
+++ b/common/math/integer.go
@@ -0,0 +1,25 @@
+package math
+
+import gmath "math"
+
+/*
+ * NOTE: The following methods need to be optimised using either bit checking or asm
+ */
+
+// SafeSub returns subtraction result and whether overflow occurred.
+func SafeSub(x, y uint64) (uint64, bool) {
+ return x - y, x < y
+}
+
+// SafeAdd returns the result and whether overflow occurred.
+func SafeAdd(x, y uint64) (uint64, bool) {
+ return x + y, y > gmath.MaxUint64-x
+}
+
+// SafeMul returns multiplication result and whether overflow occurred.
+func SafeMul(x, y uint64) (uint64, bool) {
+ if x == 0 {
+ return 0, false
+ }
+ return x * y, x != 0 && y != 0 && y > gmath.MaxUint64/x
+}
diff --git a/common/math/integer_test.go b/common/math/integer_test.go
new file mode 100644
index 000000000..198114e5e
--- /dev/null
+++ b/common/math/integer_test.go
@@ -0,0 +1,50 @@
+package math
+
+import (
+ gmath "math"
+ "testing"
+)
+
+type operation byte
+
+const (
+ sub operation = iota
+ add
+ mul
+)
+
+func TestOverflow(t *testing.T) {
+ for i, test := range []struct {
+ x uint64
+ y uint64
+ overflow bool
+ op operation
+ }{
+ // add operations
+ {gmath.MaxUint64, 1, true, add},
+ {gmath.MaxUint64 - 1, 1, false, add},
+
+ // sub operations
+ {0, 1, true, sub},
+ {0, 0, false, sub},
+
+ // mul operations
+ {10, 10, false, mul},
+ {gmath.MaxUint64, 2, true, mul},
+ {gmath.MaxUint64, 1, false, mul},
+ } {
+ var overflows bool
+ switch test.op {
+ case sub:
+ _, overflows = SafeSub(test.x, test.y)
+ case add:
+ _, overflows = SafeAdd(test.x, test.y)
+ case mul:
+ _, overflows = SafeMul(test.x, test.y)
+ }
+
+ if test.overflow != overflows {
+ t.Errorf("%d failed. Expected test to be %v, got %v", i, test.overflow, overflows)
+ }
+ }
+}