-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathint64.go
111 lines (95 loc) · 2.01 KB
/
int64.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package fastdiv
import "math/bits"
// Int64 calculates division by using a pre-computed inverse.
type Int64 struct {
absd uint64
hi, lo uint64
neg bool
}
// NewInt64 initializes a new pre-computed inverse.
func NewInt64(d int64) Int64 {
var neg bool
if d < 0 {
neg = true
d = -d
}
absd := uint64(d)
hi, r := ^uint64(0)/absd, ^uint64(0)%absd
lo, _ := bits.Div64(r, ^uint64(0), absd)
var c uint64 = 1
if absd&(absd-1) == 0 {
c++
}
lo, c = bits.Add64(lo, c, 0)
hi, _ = bits.Add64(hi, 0, c)
return Int64{
absd: absd,
hi: hi,
lo: lo,
neg: neg,
}
}
// Div calculates n / d using the pre-computed inverse.
// Note, must have d != 1, -1, 0, or math.MinInt32
func (d Int64) Div(n int64) int64 {
neg := d.neg
if n < 0 {
n = -n
neg = !neg
}
divlo1, _ := bits.Mul64(d.lo, uint64(n))
div, divlo2 := bits.Mul64(d.hi, uint64(n))
var c uint64
_, c = bits.Add64(divlo1, divlo2, 0)
div, _ = bits.Add64(div, 0, c)
if neg {
return -int64(div)
}
return int64(div)
}
// Mod calculates n % d using the pre-computed inverse.
func (d Int64) Mod(n int64) int64 {
var neg bool
if n < 0 {
n = -n
neg = true
}
hi, lo := bits.Mul64(d.lo, uint64(n))
hi += d.hi * uint64(n)
modlo1, _ := bits.Mul64(lo, d.absd)
mod, modlo2 := bits.Mul64(hi, d.absd)
var c uint64
_, c = bits.Add64(modlo1, modlo2, 0)
mod, _ = bits.Add64(mod, 0, c)
if neg {
return -int64(mod)
}
return int64(mod)
}
// DivMod calculates n / d and n % d using the pre-computed inverse.
// Note, must have d != 1, -1, 0, or math.MinInt32
func (d Int64) DivMod(n int64) (q, r int64) {
var neg bool
if n < 0 {
n = -n
neg = true
}
divlo1, lo := bits.Mul64(d.lo, uint64(n))
div, divlo2 := bits.Mul64(d.hi, uint64(n))
hi, c := bits.Add64(divlo1, divlo2, 0)
div, _ = bits.Add64(div, 0, c)
q = int64(div)
modlo1, _ := bits.Mul64(lo, d.absd)
mod, modlo2 := bits.Mul64(hi, d.absd)
_, c = bits.Add64(modlo1, modlo2, 0)
mod, _ = bits.Add64(mod, 0, c)
r = int64(mod)
if neg {
q = -q
r = -r
}
if d.neg {
q = -q
}
return q, r
}