Skip to content

Commit dfed375

Browse files
committed
algorithmic fixes and test coverage
1 parent b11ae50 commit dfed375

File tree

2 files changed

+175
-10
lines changed

2 files changed

+175
-10
lines changed

overflow.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func Add32(a, b int32) (int32, bool) {
4343

4444
// because the signs of the addends are the same,
4545
// the signs of the result should match.
46-
if (c > 0) == (a > 0) {
46+
if (c >= 0) == (a >= 0) {
4747
return c, true
4848
}
4949

@@ -55,14 +55,21 @@ func Sub32(a, b int32) (int32, bool) {
5555

5656
// the abs(math.Minint) is greater then math.Maxint
5757
if b == math.MinInt32 {
58-
return 0, false
58+
if a >= 0 {
59+
return 0, false
60+
}
61+
a++
62+
b++
5963
}
6064

6165
// otherwise, it's addition
6266
return Add32(a, -b)
6367
}
6468

6569
func Mul32(a, b int32) (int32, bool) {
70+
if (a == math.MinInt32 && b == -1) || (a == -1 && b == math.MinInt32) {
71+
return 0, false
72+
}
6673
if a == 0 || b == 0 {
6774
return 0, true
6875
}
@@ -83,8 +90,8 @@ func Quotient32(a, b int32) (int32, int32, bool) {
8390
if b == 0 {
8491
return 0, 0, false
8592
}
86-
// only one possible failure
87-
if a == math.MinInt32 && b == -1 {
93+
// only two possible overflows
94+
if (a == math.MinInt32 && b == -1) || (a == -1 && b == math.MinInt32) {
8895
return 0, 0, false
8996
}
9097
return a / b, a % b, true
@@ -108,7 +115,7 @@ func Add64(a, b int64) (int64, bool) {
108115

109116
// because the signs of the addends are the same,
110117
// the signs of the result should match.
111-
if (c > 0) == (a > 0) {
118+
if (c >= 0) == (a >= 0) {
112119
return c, true
113120
}
114121

@@ -120,14 +127,21 @@ func Sub64(a, b int64) (int64, bool) {
120127

121128
// the abs(math.Minint) is greater then math.Maxint
122129
if b == math.MinInt64 {
123-
return 0, false
130+
if a >= 0 {
131+
return 0, false
132+
}
133+
a++
134+
b++
124135
}
125136

126137
// otherwise, it's addition
127138
return Add64(a, -b)
128139
}
129140

130141
func Mul64(a, b int64) (int64, bool) {
142+
if (a == math.MinInt64 && b == -1) || (a == -1 && b == math.MinInt64) {
143+
return 0, false
144+
}
131145
if a == 0 || b == 0 {
132146
return 0, true
133147
}
@@ -148,10 +162,11 @@ func Quotient64(a, b int64) (int64, int64, bool) {
148162
if b == 0 {
149163
return 0, 0, false
150164
}
151-
// only one possible failure
152-
if a == math.MinInt64 && b == -1 {
165+
// only two possible overflows
166+
if (a == math.MinInt64 && b == -1) || (a == -1 && b == math.MinInt64) {
153167
return 0, 0, false
154168
}
169+
155170
return a / b, a % b, true
156171
}
157172

overflow_test.go

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,149 @@ import (
66
)
77
import "fmt"
88

9+
// sample all possibilities of 8 bit numbers
10+
// by checking against 64 bit numbers
11+
12+
func TestAlgorithms(t *testing.T) {
13+
14+
add8 := func(a, b int8) (int8, bool) {
15+
c := a + b
16+
if a == 0 || b == 0 {
17+
return c, true
18+
}
19+
if (a > 0) != (b > 0) {
20+
return c, true
21+
}
22+
if (c >= 0) == (a >= 0) {
23+
return c, true
24+
}
25+
return 0, false
26+
}
27+
28+
sub8 := func(a, b int8) (int8, bool) {
29+
30+
if b == math.MinInt8 {
31+
if a >= 0 {
32+
return 0, false
33+
}
34+
a++
35+
b++
36+
}
37+
38+
return add8(a, -b)
39+
}
40+
41+
mul8 := func(a, b int8) (int8, bool) {
42+
if (a == math.MinInt8 && b == -1) || (a == -1 && b == math.MinInt8) {
43+
return 0, false
44+
}
45+
if a == 0 || b == 0 {
46+
return 0, true
47+
}
48+
c := a * b
49+
if c/b == a {
50+
return c, true
51+
}
52+
return 0, false
53+
}
54+
55+
quotient8 := func(a, b int8) (int8, int8, bool) {
56+
57+
if b == 0 {
58+
return 0, 0, false
59+
}
60+
// only two possible overflows
61+
if (a == math.MinInt8 && b == -1) || (a == -1 && b == math.MinInt8) {
62+
return 0, 0, false
63+
}
64+
return a / b, a % b, true
65+
}
66+
67+
for a64 := int64(math.MinInt8); a64 <= int64(math.MaxInt8); a64++ {
68+
69+
for b64 := int64(math.MinInt8); b64 <= int64(math.MaxInt8); b64++ {
70+
a8 := int8(a64)
71+
b8 := int8(b64)
72+
if int64(a8) != a64 || int64(b8) != b64 {
73+
t.Fatal("LOGIC FAILURE IN TEST")
74+
}
75+
76+
// ADDITION
77+
{
78+
r64 := a64 + b64
79+
r8 := a8 + b8
80+
81+
// now the verification
82+
result, ok := add8(a8, b8)
83+
if ok {
84+
if int64(result) != r64 {
85+
t.Errorf("failed to fail on %v + %v = %v instead of %v\n", a8, b8, result, r64)
86+
}
87+
} else {
88+
if result != 0 && result == r8 {
89+
t.Errorf("failed to fail on %v + %v = %v instead of %v\n", a8, b8, result, r64)
90+
}
91+
}
92+
}
93+
94+
// SUBTRACTION
95+
{
96+
r64 := a64 - b64
97+
r8 := a8 - b8
98+
99+
// now the verification
100+
result, ok := sub8(a8, b8)
101+
if ok {
102+
if int64(result) != r64 {
103+
t.Errorf("failed to fail on %v - %v = %v instead of %v\n", a8, b8, result, r64)
104+
}
105+
} else {
106+
if result != 0 && result == r8 {
107+
t.Errorf("failed to fail on %v - %v = %v instead of %v\n", a8, b8, result, r64)
108+
}
109+
}
110+
}
111+
112+
// MULTIPLICATION
113+
{
114+
r64 := a64 * b64
115+
r8 := a8 * b8
116+
117+
// now the verification
118+
result, ok := mul8(a8, b8)
119+
if ok {
120+
if int64(result) != r64 {
121+
t.Errorf("failed to fail on %v * %v = %v instead of %v\n", a8, b8, result, r64)
122+
}
123+
} else {
124+
if result != 0 && result == r8 {
125+
t.Errorf("failed to fail on %v * %v = %v instead of %v\n", a8, b8, result, r64)
126+
}
127+
}
128+
}
129+
130+
// DIVISION
131+
if b8 != 0 {
132+
r64 := a64 / b64
133+
r8 := a8 / b8
134+
135+
// now the verification
136+
result, _, ok := quotient8(a8, b8)
137+
if ok {
138+
if int64(result) != r64 {
139+
t.Errorf("failed to fail on %v / %v = %v instead of %v\n", a8, b8, result, r64)
140+
}
141+
} else {
142+
if result != 0 && result == r8 {
143+
t.Errorf("failed to fail on %v / %v = %v instead of %v\n", a8, b8, result, r64)
144+
}
145+
}
146+
}
147+
}
148+
}
149+
150+
}
151+
9152
func TestOperations32(t *testing.T) {
10153
table := []struct {
11154
f string
@@ -20,6 +163,8 @@ func TestOperations32(t *testing.T) {
20163
{"+", math.MaxInt32, math.MaxInt32, false, 0},
21164
{"+", math.MinInt32 + 100, 101, true, math.MinInt32 + 201},
22165

166+
{"-", -1, math.MinInt32, true, math.MaxInt32},
167+
{"-", math.MinInt32, -1, true, math.MinInt32 + 1},
23168
{"-", math.MaxInt32, 1, true, math.MaxInt32 - 1},
24169
{"-", math.MaxInt32, -1, false, 0},
25170
{"-", 0, math.MinInt32, false, 0},
@@ -28,6 +173,7 @@ func TestOperations32(t *testing.T) {
28173
{"-", math.MaxInt32, math.MaxInt32, true, 0},
29174
{"-", math.MinInt32 + 100, 101, false, 0},
30175

176+
{"*", math.MinInt32, -1, false, 0},
31177
{"*", math.MaxInt32, 1, true, math.MaxInt32},
32178
{"*", math.MaxInt32, -1, true, math.MinInt32 + 1},
33179
{"*", 0, 0, true, 0},
@@ -96,6 +242,7 @@ func TestOperations64(t *testing.T) {
96242
{"+", math.MaxInt64, math.MaxInt64, false, 0},
97243
{"+", math.MinInt64 + 100, 101, true, math.MinInt64 + 201},
98244

245+
{"-", -1, math.MinInt64, true, math.MaxInt64},
99246
{"-", math.MaxInt64, 1, true, math.MaxInt64 - 1},
100247
{"-", math.MaxInt64, -1, false, 0},
101248
{"-", 0, math.MinInt64, false, 0},
@@ -104,6 +251,7 @@ func TestOperations64(t *testing.T) {
104251
{"-", math.MaxInt64, math.MaxInt64, true, 0},
105252
{"-", math.MinInt64 + 100, 101, false, 0},
106253

254+
{"*", math.MinInt64, -1, false, 0},
107255
{"*", math.MaxInt64, 1, true, math.MaxInt64},
108256
{"*", math.MaxInt64, -1, true, math.MinInt64 + 1},
109257
{"*", 0, 0, true, 0},
@@ -271,10 +419,12 @@ func TestQuotient(t *testing.T) {
271419
}
272420

273421
//func TestAdditionInt(t *testing.T) {
422+
// fmt.Printf("\nminint8 = %v\n", math.MinInt8)
423+
// fmt.Printf("maxint8 = %v\n\n", math.MaxInt8)
274424
// fmt.Printf("maxint32 = %v\n", math.MaxInt32)
275-
// fmt.Printf("minint32 = %v\n", math.MinInt32)
425+
// fmt.Printf("minint32 = %v\n\n", math.MinInt32)
276426
// fmt.Printf("maxint64 = %v\n", math.MaxInt64)
277-
// fmt.Printf("minint64 = %v\n", math.MinInt64)
427+
// fmt.Printf("minint64 = %v\n\n", math.MinInt64)
278428
//}
279429

280430
func Test64(t *testing.T) {

0 commit comments

Comments
 (0)