Skip to content

Commit 06d7f97

Browse files
committed
Add readme about new features, improve comments, and add an corner test case
1 parent e5a4341 commit 06d7f97

File tree

5 files changed

+132
-108
lines changed

5 files changed

+132
-108
lines changed

README.md

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
# overflow
33
Check for integer overflow in Golang arithmetic and type conversion.
44
### Install
5-
```
5+
```sh
66
go get github.com/johncgriffin/overflow
77
```
88
Note that because Go has no template types, the majority of repetitive code is
99
generated by overflow_template.sh. If you have to change an
1010
algorithm, change it there and regenerate the Go code via:
11-
```
11+
```sh
1212
go generate
1313
```
1414
### Synopsis
1515

1616
#### Arithmetic overflow detection
17-
```
17+
```go
1818
package main
1919

2020
import "fmt"
@@ -34,7 +34,7 @@ func main() {
3434
}
3535
```
3636
yields the output
37-
```
37+
```go
3838
9223372036854775802+0 -> (9223372036854775802,true)
3939
9223372036854775802+1 -> (9223372036854775803,true)
4040
9223372036854775802+2 -> (9223372036854775804,true)
@@ -51,7 +51,7 @@ For (u)int types, provide (U)Add, (U)Sub, (U)Mul, (U)Div, (U)Quotient, etc.
5151

5252

5353
#### Type conversion overflow detection
54-
```
54+
```go
5555
func main() {
5656
var i uint
5757
for i = math.MaxInt - 5; i <= math.MaxInt+5; i++ {
@@ -62,7 +62,7 @@ func main() {
6262
}
6363
```
6464
yields the output
65-
```
65+
```go
6666
9223372036854775802 -> (9223372036854775802,true)
6767
9223372036854775803 -> (9223372036854775803,true)
6868
9223372036854775804 -> (9223372036854775804,true)
@@ -83,6 +83,27 @@ There's a good case to be made that a panic is an unidiomatic but proper respons
8383
believe that there's no valid way to continue your program after math goes wayward, you can
8484
use the easier Addp, Mulp, Subp, and Divp versions which return the normal result or panic.
8585

86+
### Performance considerations
87+
88+
Compared with the integer type safety libraries of other languages (such as C++), this
89+
library uses some seemingly slow operations, such as division. But this does not mean that
90+
these methods will be slow, on the contrary, it will be faster than complex implementations
91+
in other languages. The reason is that Go does not allow forced inlining, and any complex
92+
functions will be abandoned for inlining, resulting in additional calling overhead. Short
93+
functions are lightning fast due to automatic inlining. For example, for unsigned 64-bit
94+
integer multiplication overflow detection, when inlining is disabled, division takes five
95+
times as long as long multiplication, but after automatic inlining is allowed, division
96+
takes 1/5 of long multiplication.
97+
98+
Note that using `//go:noinline` in your business function will not affect the inlining of
99+
the library function. Only disabling global inlining through `-gcflags="-l"` will affect the
100+
inlining of this library function.
101+
102+
### Basis and dependencies
103+
104+
This library is based on Go's official compiler implementation and language specification,
105+
which defines the behavior when integer overflow occurs.
106+
86107

87108
- - -
88109
MIT License

overflow.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ So, FEEL FREE to carefully review the code visually.
4242

4343
// Unspecified size, i.e. normal signed int
4444

45-
// Add sums two ints, returning the result and a boolean status.
45+
// Add sums two ints, returning the result and a ok result indicating whether the operation is safe.
4646
func Add(a, b int) (int, bool) {
4747
if _is64Bit() {
4848
r64, ok := Add64(int64(a), int64(b))
@@ -52,7 +52,7 @@ func Add(a, b int) (int, bool) {
5252
return int(r32), ok
5353
}
5454

55-
// UAdd sums two uints, returning the result and a boolean status.
55+
// UAdd sums two uints, returning the result and a ok result indicating whether the operation is safe.
5656
func UAdd(a, b uint) (uint, bool) {
5757
if _is64Bit() {
5858
r64, ok := UAdd64(uint64(a), uint64(b))
@@ -62,7 +62,7 @@ func UAdd(a, b uint) (uint, bool) {
6262
return uint(r32), ok
6363
}
6464

65-
// Sub returns the difference of two ints and a boolean status.
65+
// Sub returns the difference of two ints and a ok result indicating whether the operation is safe.
6666
func Sub(a, b int) (int, bool) {
6767
if _is64Bit() {
6868
r64, ok := Sub64(int64(a), int64(b))
@@ -72,7 +72,7 @@ func Sub(a, b int) (int, bool) {
7272
return int(r32), ok
7373
}
7474

75-
// USub returns the difference of two uints and a boolean status.
75+
// USub returns the difference of two uints and a ok result indicating whether the operation is safe.
7676
func USub(a, b uint) (uint, bool) {
7777
if _is64Bit() {
7878
r64, ok := USub64(uint64(a), uint64(b))
@@ -82,7 +82,7 @@ func USub(a, b uint) (uint, bool) {
8282
return uint(r32), ok
8383
}
8484

85-
// Mul returns the product of two ints and a boolean status.
85+
// Mul returns the product of two ints and a ok result indicating whether the operation is safe.
8686
func Mul(a, b int) (int, bool) {
8787
if _is64Bit() {
8888
r64, ok := Mul64(int64(a), int64(b))
@@ -92,7 +92,7 @@ func Mul(a, b int) (int, bool) {
9292
return int(r32), ok
9393
}
9494

95-
// UMul returns the product of two uints and a boolean status.
95+
// UMul returns the product of two uints and a ok result indicating whether the operation is safe.
9696
func UMul(a, b uint) (uint, bool) {
9797
if _is64Bit() {
9898
r64, ok := UMul64(uint64(a), uint64(b))
@@ -102,7 +102,7 @@ func UMul(a, b uint) (uint, bool) {
102102
return uint(r32), ok
103103
}
104104

105-
// Div returns the quotient of two ints and a boolean status
105+
// Div returns the quotient of two ints and a ok result indicating whether the operation is safe.
106106
func Div(a, b int) (int, bool) {
107107
if _is64Bit() {
108108
r64, ok := Div64(int64(a), int64(b))
@@ -112,7 +112,7 @@ func Div(a, b int) (int, bool) {
112112
return int(r32), ok
113113
}
114114

115-
// UDiv returns the quotient of two uints and a boolean status
115+
// UDiv returns the quotient of two uints and a ok result indicating whether the operation is safe.
116116
func UDiv(a, b uint) (uint, bool) {
117117
if _is64Bit() {
118118
r64, ok := UDiv64(uint64(a), uint64(b))
@@ -122,7 +122,7 @@ func UDiv(a, b uint) (uint, bool) {
122122
return uint(r32), ok
123123
}
124124

125-
// Quotient returns the quotient, remainder and status of two ints
125+
// Quotient returns the quotient, remainder and ok result indicating whether the operation is safe.
126126
func Quotient(a, b int) (int, int, bool) {
127127
if _is64Bit() {
128128
q64, r64, ok := Quotient64(int64(a), int64(b))
@@ -132,7 +132,7 @@ func Quotient(a, b int) (int, int, bool) {
132132
return int(q32), int(r32), ok
133133
}
134134

135-
// UQuotient returns the quotient, remainder and status of two uints
135+
// UQuotient returns the quotient, remainder and ok result indicating whether the operation is safe.
136136
func UQuotient(a, b uint) (uint, uint, bool) {
137137
if _is64Bit() {
138138
uq64, ur64, ok := UQuotient64(uint64(a), uint64(b))

0 commit comments

Comments
 (0)