github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/go/math/big/arith.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file provides Go implementations of elementary multi-precision 6 // arithmetic operations on word vectors. Needed for platforms without 7 // assembly implementations of these routines. 8 9 package big 10 11 // A Word represents a single digit of a multi-precision unsigned integer. 12 type Word uintptr 13 14 const ( 15 // Compute the size _S of a Word in bytes. 16 _m = ^Word(0) 17 _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 18 _S = 1 << _logS 19 20 _W = _S << 3 // word size in bits 21 _B = 1 << _W // digit base 22 _M = _B - 1 // digit mask 23 24 _W2 = _W / 2 // half word size in bits 25 _B2 = 1 << _W2 // half digit base 26 _M2 = _B2 - 1 // half digit mask 27 ) 28 29 // ---------------------------------------------------------------------------- 30 // Elementary operations on words 31 // 32 // These operations are used by the vector operations below. 33 34 // z1<<_W + z0 = x+y+c, with c == 0 or 1 35 func addWW_g(x, y, c Word) (z1, z0 Word) { 36 yc := y + c 37 z0 = x + yc 38 if z0 < x || yc < y { 39 z1 = 1 40 } 41 return 42 } 43 44 // z1<<_W + z0 = x-y-c, with c == 0 or 1 45 func subWW_g(x, y, c Word) (z1, z0 Word) { 46 yc := y + c 47 z0 = x - yc 48 if z0 > x || yc < y { 49 z1 = 1 50 } 51 return 52 } 53 54 // z1<<_W + z0 = x*y 55 func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) } 56 57 // Adapted from Warren, Hacker's Delight, p. 132. 58 func mulWW_g(x, y Word) (z1, z0 Word) { 59 x0 := x & _M2 60 x1 := x >> _W2 61 y0 := y & _M2 62 y1 := y >> _W2 63 w0 := x0 * y0 64 t := x1*y0 + w0>>_W2 65 w1 := t & _M2 66 w2 := t >> _W2 67 w1 += x0 * y1 68 z1 = x1*y1 + w2 + w1>>_W2 69 z0 = x * y 70 return 71 } 72 73 // z1<<_W + z0 = x*y + c 74 func mulAddWWW_g(x, y, c Word) (z1, z0 Word) { 75 z1, zz0 := mulWW(x, y) 76 if z0 = zz0 + c; z0 < zz0 { 77 z1++ 78 } 79 return 80 } 81 82 // Length of x in bits. 83 func bitLen(x Word) (n int) { return bitLen_g(x) } 84 func bitLen_g(x Word) (n int) { 85 for ; x >= 0x8000; x >>= 16 { 86 n += 16 87 } 88 if x >= 0x80 { 89 x >>= 8 90 n += 8 91 } 92 if x >= 0x8 { 93 x >>= 4 94 n += 4 95 } 96 if x >= 0x2 { 97 x >>= 2 98 n += 2 99 } 100 if x >= 0x1 { 101 n++ 102 } 103 return 104 } 105 106 // log2 computes the integer binary logarithm of x. 107 // The result is the integer n for which 2^n <= x < 2^(n+1). 108 // If x == 0, the result is -1. 109 func log2(x Word) int { 110 return bitLen(x) - 1 111 } 112 113 // Number of leading zeros in x. 114 func leadingZeros(x Word) uint { 115 return uint(_W - bitLen(x)) 116 } 117 118 // q = (u1<<_W + u0 - r)/y 119 func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) } 120 121 // Adapted from Warren, Hacker's Delight, p. 152. 122 func divWW_g(u1, u0, v Word) (q, r Word) { 123 if u1 >= v { 124 return 1<<_W - 1, 1<<_W - 1 125 } 126 127 s := leadingZeros(v) 128 v <<= s 129 130 vn1 := v >> _W2 131 vn0 := v & _M2 132 un32 := u1<<s | u0>>(_W-s) 133 un10 := u0 << s 134 un1 := un10 >> _W2 135 un0 := un10 & _M2 136 q1 := un32 / vn1 137 rhat := un32 - q1*vn1 138 139 for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 { 140 q1-- 141 rhat += vn1 142 if rhat >= _B2 { 143 break 144 } 145 } 146 147 un21 := un32*_B2 + un1 - q1*v 148 q0 := un21 / vn1 149 rhat = un21 - q0*vn1 150 151 for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 { 152 q0-- 153 rhat += vn1 154 if rhat >= _B2 { 155 break 156 } 157 } 158 159 return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s 160 } 161 162 func addVV(z, x, y []Word) (c Word) { return addVV_g(z, x, y) } 163 func addVV_g(z, x, y []Word) (c Word) { 164 for i := range z { 165 c, z[i] = addWW_g(x[i], y[i], c) 166 } 167 return 168 } 169 170 func subVV(z, x, y []Word) (c Word) { return subVV_g(z, x, y) } 171 func subVV_g(z, x, y []Word) (c Word) { 172 for i := range z { 173 c, z[i] = subWW_g(x[i], y[i], c) 174 } 175 return 176 } 177 178 func addVW(z, x []Word, y Word) (c Word) { return addVW_g(z, x, y) } 179 func addVW_g(z, x []Word, y Word) (c Word) { 180 c = y 181 for i := range z { 182 c, z[i] = addWW_g(x[i], c, 0) 183 } 184 return 185 } 186 187 func subVW(z, x []Word, y Word) (c Word) { return subVW_g(z, x, y) } 188 func subVW_g(z, x []Word, y Word) (c Word) { 189 c = y 190 for i := range z { 191 c, z[i] = subWW_g(x[i], c, 0) 192 } 193 return 194 } 195 196 func shlVU(z, x []Word, s uint) (c Word) { return shlVU_g(z, x, s) } 197 func shlVU_g(z, x []Word, s uint) (c Word) { 198 if n := len(z); n > 0 { 199 ŝ := _W - s 200 w1 := x[n-1] 201 c = w1 >> ŝ 202 for i := n - 1; i > 0; i-- { 203 w := w1 204 w1 = x[i-1] 205 z[i] = w<<s | w1>>ŝ 206 } 207 z[0] = w1 << s 208 } 209 return 210 } 211 212 func shrVU(z, x []Word, s uint) (c Word) { return shrVU_g(z, x, s) } 213 func shrVU_g(z, x []Word, s uint) (c Word) { 214 if n := len(z); n > 0 { 215 ŝ := _W - s 216 w1 := x[0] 217 c = w1 << ŝ 218 for i := 0; i < n-1; i++ { 219 w := w1 220 w1 = x[i+1] 221 z[i] = w>>s | w1<<ŝ 222 } 223 z[n-1] = w1 >> s 224 } 225 return 226 } 227 228 func mulAddVWW(z, x []Word, y, r Word) (c Word) { return mulAddVWW_g(z, x, y, r) } 229 func mulAddVWW_g(z, x []Word, y, r Word) (c Word) { 230 c = r 231 for i := range z { 232 c, z[i] = mulAddWWW_g(x[i], y, c) 233 } 234 return 235 } 236 237 func addMulVVW(z, x []Word, y Word) (c Word) { return addMulVVW_g(z, x, y) } 238 func addMulVVW_g(z, x []Word, y Word) (c Word) { 239 for i := range z { 240 z1, z0 := mulAddWWW_g(x[i], y, z[i]) 241 c, z[i] = addWW_g(z0, c, 0) 242 c += z1 243 } 244 return 245 } 246 247 func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { return divWVW_g(z, xn, x, y) } 248 func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) { 249 r = xn 250 for i := len(z) - 1; i >= 0; i-- { 251 z[i], r = divWW_g(r, x[i], y) 252 } 253 return 254 }