@@ -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
2323func 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
2929func 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
3737func 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
4646func 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
6459func 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
16467func 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
16972func 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
19093func 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
197100func 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
243135func 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