Skip to content

Commit e6e60c7

Browse files
removing my own tests for the original ones
1 parent 60f61e8 commit e6e60c7

3 files changed

Lines changed: 152 additions & 300 deletions

File tree

compiler/natives/src/math/bits/bits.go

Lines changed: 152 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@ var (
1919
divideError error = _err("runtime error: integer divide by zero")
2020
)
2121

22-
//gopherjs:keep-original the original is kept for testing
22+
//gopherjs:replace
2323
func LeadingZeros32(x uint32) int {
2424
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
2525
return js.Global.Get("Math").Call("clz32", x).Int()
2626
}
2727

28-
//gopherjs:keep-original the original is kept for testing
28+
//gopherjs:replace
2929
func LeadingZeros64(x uint64) int {
3030
if hi := js.Uint64High(x); hi != 0 {
3131
return LeadingZeros32(hi)
3232
}
3333
return 32 + LeadingZeros32(js.Uint64Low(x))
3434
}
3535

36-
//gopherjs:keep-original the original is kept for testing
36+
//gopherjs:replace
3737
func TrailingZeros32(x uint32) int {
3838
// See "ctrz" in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
3939
if x == 0 {
@@ -42,7 +42,7 @@ func TrailingZeros32(x uint32) int {
4242
return 31 - LeadingZeros32(x&-x)
4343
}
4444

45-
//gopherjs:keep-original the original is kept for testing
45+
//gopherjs:replace
4646
func TrailingZeros64(x uint64) int {
4747
lo := js.Uint64Low(x)
4848
if lo != 0 {
@@ -55,117 +55,20 @@ func TrailingZeros64(x uint64) int {
5555
return 63 - LeadingZeros32(hi&-hi)
5656
}
5757

58-
//gopherjs:keep-original the original is kept for testing
59-
func Len32(x uint32) int {
60-
return 32 - LeadingZeros32(x)
61-
}
62-
63-
//gopherjs:keep-original the original is kept for testing
58+
//gopherjs:replace
6459
func OnesCount32(x uint32) int {
6560
x = x - ((x >> 1) & 0x55555555)
6661
x = (x & 0x33333333) + ((x >> 2) & 0x33333333)
6762
x = (x + (x >> 4)) & 0x0F0F0F0F
6863
return int((x * 0x01010101) >> 24)
6964
}
7065

71-
//gopherjs:keep-original the original is kept for testing
72-
func Mul32(x, y uint32) (hi, lo uint32) {
73-
// Avoid slow 64-bit integers for better performance. Adapted from Mul64().
74-
const mask16 = 1<<16 - 1
75-
x0 := x & mask16
76-
x1 := x >> 16
77-
y0 := y & mask16
78-
y1 := y >> 16
79-
w0 := x0 * y0
80-
t := x1*y0 + w0>>16
81-
w1 := t & mask16
82-
w2 := t >> 16
83-
w1 += x0 * y1
84-
hi = x1*y1 + w2 + w1>>16
85-
lo = x * y
86-
return
87-
}
88-
89-
//gopherjs:keep-original the original is kept for testing
90-
func Add32(x, y, carry uint32) (sum, carryOut uint32) {
91-
// Avoid slow 64-bit integers for better performance. Adapted from Add64().
92-
sum = x + y + carry
93-
carryOut = ((x & y) | ((x | y) &^ sum)) >> 31
94-
return
95-
}
96-
97-
//gopherjs:keep-original the original is kept for testing
98-
func Div32(hi, lo, y uint32) (quo, rem uint32) {
99-
// Avoid slow 64-bit integers for better performance. Adapted from Div64().
100-
const (
101-
two16 = 1 << 16
102-
mask16 = two16 - 1
103-
)
104-
if y == 0 {
105-
panic(divideError)
106-
}
107-
if y <= hi {
108-
panic(overflowError)
109-
}
110-
111-
s := uint(LeadingZeros32(y))
112-
y <<= s
113-
114-
yn1 := y >> 16
115-
yn0 := y & mask16
116-
un16 := hi<<s | lo>>(32-s)
117-
un10 := lo << s
118-
un1 := un10 >> 16
119-
un0 := un10 & mask16
120-
q1 := un16 / yn1
121-
rhat := un16 - q1*yn1
122-
123-
for q1 >= two16 || q1*yn0 > two16*rhat+un1 {
124-
q1--
125-
rhat += yn1
126-
if rhat >= two16 {
127-
break
128-
}
129-
}
130-
131-
un21 := un16*two16 + un1 - q1*y
132-
q0 := un21 / yn1
133-
rhat = un21 - q0*yn1
134-
135-
for q0 >= two16 || q0*yn0 > two16*rhat+un0 {
136-
q0--
137-
rhat += yn1
138-
if rhat >= two16 {
139-
break
140-
}
141-
}
142-
143-
return q1*two16 + q0, (un21*two16 + un0 - q0*y) >> s
144-
}
145-
146-
//gopherjs:keep-original the original is kept for testing
147-
func Rem32(hi, lo, y uint32) uint32 {
148-
// We scale down hi so that hi < y, then use Div32 to compute the
149-
// rem with the guarantee that it won't panic on quotient overflow.
150-
// Given that
151-
// hi ≡ hi%y (mod y)
152-
// we have
153-
// hi<<64 + lo ≡ (hi%y)<<64 + lo (mod y)
154-
_, rem := Div32(hi%y, lo, y)
155-
return rem
156-
}
157-
158-
//gopherjs:keep-original the original is kept for testing
159-
func Len64(x uint64) int {
160-
return 64 - LeadingZeros64(x)
161-
}
162-
163-
//gopherjs:keep-original the original is kept for testing
66+
//gopherjs:replace
16467
func OnesCount64(x uint64) int {
16568
return OnesCount32(js.Uint64High(x)) + OnesCount32(js.Uint64Low(x))
16669
}
16770

168-
//gopherjs:keep-original the original is kept for testing
71+
//gopherjs:replace
16972
func RotateLeft64(x uint64, k int) uint64 {
17073
s := uint32(k) & 63
17174
if s == 0 {
@@ -186,60 +89,49 @@ func RotateLeft64(x uint64, k int) uint64 {
18689
return js.MakeUint64(float64(xHi<<s|xLo>>rs), float64(xLo<<s|xHi>>rs))
18790
}
18891

189-
//gopherjs:keep-original the original is kept for testing
92+
//gopherjs:replace
19093
func Reverse64(x uint64) uint64 {
19194
return js.MakeUint64(
19295
float64(Reverse32(js.Uint64Low(x))),
19396
float64(Reverse32(js.Uint64High(x))))
19497
}
19598

196-
//gopherjs:keep-original the original is kept for testing
99+
//gopherjs:replace
197100
func ReverseBytes64(x uint64) uint64 {
198101
return js.MakeUint64(
199102
float64(ReverseBytes32(js.Uint64Low(x))),
200103
float64(ReverseBytes32(js.Uint64High(x))))
201104
}
202105

203-
//gopherjs:keep-original the original is kept for testing
204-
func Add64(x, y, carry uint64) (sum, carryOut uint64) {
205-
// Decompose into 32-bit halves and perform the addition as float64,
206-
// where JS can represent integers up to 2^53 exactly. js.MakeUint64
207-
// handles low->high carry propagation automatically.
208-
hiSum := float64(js.Uint64High(x)) + float64(js.Uint64High(y))
209-
loSum := float64(js.Uint64Low(x)) + float64(js.Uint64Low(y)) + float64(js.Uint64Low(carry))
210-
sum = js.MakeUint64(hiSum, loSum)
211-
212-
// Carry-out = 1 iff (hiSum + low->high carry) >= 2^32.
213-
if loSum >= 4294967296.0 {
214-
hiSum++
215-
}
216-
if hiSum >= 4294967296.0 {
217-
carryOut = 1
218-
}
219-
return
106+
//gopherjs:replace
107+
func Len32(x uint32) int {
108+
return 32 - LeadingZeros32(x)
220109
}
221110

222-
//gopherjs:keep-original the original is kept for testing
223-
func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) {
224-
// Mirror of nativeAdd64. The $Uint64 constructor correctly handles a
225-
// negative `low` value: Math.floor(negative/2^32) returns -1, which
226-
// propagates the borrow into the high half automatically.
227-
hiDiff := float64(js.Uint64High(x)) - float64(js.Uint64High(y))
228-
loDiff := float64(js.Uint64Low(x)) - float64(js.Uint64Low(y)) - float64(js.Uint64Low(borrow))
229-
diff = js.MakeUint64(hiDiff, loDiff)
111+
//gopherjs:replace
112+
func Len64(x uint64) int {
113+
return 64 - LeadingZeros64(x)
114+
}
230115

231-
// Borrow-out = 1 iff the conceptual signed result (hiDiff*2^32 + loDiff)
232-
// is negative:
233-
// hiDiff > 0: result definitely >= 0 (loDiff > -2^32).
234-
// hiDiff = 0: result negative iff loDiff < 0.
235-
// hiDiff < 0: result definitely < 0.
236-
if hiDiff < 0 || (hiDiff == 0 && loDiff < 0) {
237-
borrowOut = 1
238-
}
116+
//gopherjs:replace
117+
func Mul32(x, y uint32) (hi, lo uint32) {
118+
// Avoid slow 64-bit integers for better performance. Adapted from Mul64().
119+
const mask16 = 1<<16 - 1
120+
x0 := x & mask16
121+
x1 := x >> 16
122+
y0 := y & mask16
123+
y1 := y >> 16
124+
w0 := x0 * y0
125+
t := x1*y0 + w0>>16
126+
w1 := t & mask16
127+
w2 := t >> 16
128+
w1 += x0 * y1
129+
hi = x1*y1 + w2 + w1>>16
130+
lo = x * y
239131
return
240132
}
241133

242-
//gopherjs:keep-original the original is kept for testing
134+
//gopherjs:replace
243135
func Mul64(x, y uint64) (uint64, uint64) {
244136
const (
245137
bit32 = 1 << 32
@@ -285,3 +177,123 @@ func Mul64(x, y uint64) (uint64, uint64) {
285177
bit32*float64(x3*y3) // bits 96..128
286178
return js.MakeUint64(hiHi, hiLo), js.MakeUint64(mid, float64(loLo))
287179
}
180+
181+
//gopherjs:replace
182+
func Add32(x, y, carry uint32) (sum, carryOut uint32) {
183+
// Avoid slow 64-bit integers for better performance. Adapted from Add64().
184+
sum = x + y + carry
185+
carryOut = ((x & y) | ((x | y) &^ sum)) >> 31
186+
return
187+
}
188+
189+
//gopherjs:replace
190+
func Add64(x, y, carry uint64) (sum, carryOut uint64) {
191+
// Decompose into 32-bit halves and perform the addition as float64,
192+
// where JS can represent integers up to 2^53 exactly. js.MakeUint64
193+
// handles low->high carry propagation automatically.
194+
hiSum := float64(js.Uint64High(x)) + float64(js.Uint64High(y))
195+
loSum := float64(js.Uint64Low(x)) + float64(js.Uint64Low(y)) + float64(js.Uint64Low(carry))
196+
sum = js.MakeUint64(hiSum, loSum)
197+
198+
// Carry-out = 1 iff (hiSum + low->high carry) >= 2^32.
199+
if loSum >= 4294967296.0 {
200+
hiSum++
201+
}
202+
if hiSum >= 4294967296.0 {
203+
carryOut = 1
204+
}
205+
return
206+
}
207+
208+
//gopherjs:replace
209+
func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) {
210+
// Mirror of nativeAdd64. The $Uint64 constructor correctly handles a
211+
// negative `low` value: Math.floor(negative/2^32) returns -1, which
212+
// propagates the borrow into the high half automatically.
213+
hiDiff := float64(js.Uint64High(x)) - float64(js.Uint64High(y))
214+
loDiff := float64(js.Uint64Low(x)) - float64(js.Uint64Low(y)) - float64(js.Uint64Low(borrow))
215+
diff = js.MakeUint64(hiDiff, loDiff)
216+
217+
// Borrow-out = 1 iff the conceptual signed result (hiDiff*2^32 + loDiff)
218+
// is negative:
219+
// hiDiff > 0: result definitely >= 0 (loDiff > -2^32).
220+
// hiDiff = 0: result negative iff loDiff < 0.
221+
// hiDiff < 0: result definitely < 0.
222+
if hiDiff < 0 || (hiDiff == 0 && loDiff < 0) {
223+
borrowOut = 1
224+
}
225+
return
226+
}
227+
228+
//gopherjs:replace
229+
func Div32(hi, lo, y uint32) (quo, rem uint32) {
230+
// Avoid slow 64-bit integers for better performance. Adapted from Div64().
231+
const (
232+
two16 = 1 << 16
233+
mask16 = two16 - 1
234+
)
235+
if y == 0 {
236+
panic(divideError)
237+
}
238+
if y <= hi {
239+
panic(overflowError)
240+
}
241+
242+
s := uint(LeadingZeros32(y))
243+
y <<= s
244+
245+
yn1 := y >> 16
246+
yn0 := y & mask16
247+
un16 := hi<<s | lo>>(32-s)
248+
un10 := lo << s
249+
un1 := un10 >> 16
250+
un0 := un10 & mask16
251+
q1 := un16 / yn1
252+
rhat := un16 - q1*yn1
253+
254+
for q1 >= two16 || q1*yn0 > two16*rhat+un1 {
255+
q1--
256+
rhat += yn1
257+
if rhat >= two16 {
258+
break
259+
}
260+
}
261+
262+
un21 := un16*two16 + un1 - q1*y
263+
q0 := un21 / yn1
264+
rhat = un21 - q0*yn1
265+
266+
for q0 >= two16 || q0*yn0 > two16*rhat+un0 {
267+
q0--
268+
rhat += yn1
269+
if rhat >= two16 {
270+
break
271+
}
272+
}
273+
274+
return q1*two16 + q0, (un21*two16 + un0 - q0*y) >> s
275+
}
276+
277+
//gopherjs:keep-original
278+
func Div64(hi, lo, y uint64) (quo, rem uint64) {
279+
// TODO(grantnelson-wf): Add override or remove
280+
return _gopherjs_original_Div64(hi, lo, y)
281+
}
282+
283+
//gopherjs:replace
284+
func Rem32(hi, lo, y uint32) uint32 {
285+
// We scale down hi so that hi < y, then use Div32 to compute the
286+
// rem with the guarantee that it won't panic on quotient overflow.
287+
// Given that
288+
// hi ≡ hi%y (mod y)
289+
// we have
290+
// hi<<64 + lo ≡ (hi%y)<<64 + lo (mod y)
291+
_, rem := Div32(hi%y, lo, y)
292+
return rem
293+
}
294+
295+
//gopherjs:keep-original
296+
func Rem64(hi, lo, y uint64) uint64 {
297+
// TODO(grantnelson-wf): Add override or remove
298+
return _gopherjs_original_Rem64(hi, lo, y)
299+
}

0 commit comments

Comments
 (0)