github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/natives/src/math/bits/bits.go (about) 1 //go:build js 2 // +build js 3 4 package bits 5 6 type _err string 7 8 func (e _err) Error() string { 9 return string(e) 10 } 11 12 // RuntimeError implements runtime.Error. 13 func (e _err) RuntimeError() { 14 } 15 16 var ( 17 overflowError error = _err("runtime error: integer overflow") 18 divideError error = _err("runtime error: integer divide by zero") 19 ) 20 21 func Mul32(x, y uint32) (hi, lo uint32) { 22 // Avoid slow 64-bit integers for better performance. Adapted from Mul64(). 23 const mask16 = 1<<16 - 1 24 x0 := x & mask16 25 x1 := x >> 16 26 y0 := y & mask16 27 y1 := y >> 16 28 w0 := x0 * y0 29 t := x1*y0 + w0>>16 30 w1 := t & mask16 31 w2 := t >> 16 32 w1 += x0 * y1 33 hi = x1*y1 + w2 + w1>>16 34 lo = x * y 35 return 36 } 37 38 func Add32(x, y, carry uint32) (sum, carryOut uint32) { 39 // Avoid slow 64-bit integers for better performance. Adapted from Add64(). 40 sum = x + y + carry 41 carryOut = ((x & y) | ((x | y) &^ sum)) >> 31 42 return 43 } 44 45 func Div32(hi, lo, y uint32) (quo, rem uint32) { 46 // Avoid slow 64-bit integers for better performance. Adapted from Div64(). 47 const ( 48 two16 = 1 << 16 49 mask16 = two16 - 1 50 ) 51 if y == 0 { 52 panic(divideError) 53 } 54 if y <= hi { 55 panic(overflowError) 56 } 57 58 s := uint(LeadingZeros32(y)) 59 y <<= s 60 61 yn1 := y >> 16 62 yn0 := y & mask16 63 un16 := hi<<s | lo>>(32-s) 64 un10 := lo << s 65 un1 := un10 >> 16 66 un0 := un10 & mask16 67 q1 := un16 / yn1 68 rhat := un16 - q1*yn1 69 70 for q1 >= two16 || q1*yn0 > two16*rhat+un1 { 71 q1-- 72 rhat += yn1 73 if rhat >= two16 { 74 break 75 } 76 } 77 78 un21 := un16*two16 + un1 - q1*y 79 q0 := un21 / yn1 80 rhat = un21 - q0*yn1 81 82 for q0 >= two16 || q0*yn0 > two16*rhat+un0 { 83 q0-- 84 rhat += yn1 85 if rhat >= two16 { 86 break 87 } 88 } 89 90 return q1*two16 + q0, (un21*two16 + un0 - q0*y) >> s 91 } 92 93 func Rem32(hi, lo, y uint32) uint32 { 94 // We scale down hi so that hi < y, then use Div32 to compute the 95 // rem with the guarantee that it won't panic on quotient overflow. 96 // Given that 97 // hi ≡ hi%y (mod y) 98 // we have 99 // hi<<64 + lo ≡ (hi%y)<<64 + lo (mod y) 100 _, rem := Div32(hi%y, lo, y) 101 return rem 102 }