 |
Changeset 3829
- Timestamp:
- 07/31/08 03:43:58
(4 months ago)
- Author:
- Don Clugston
- Message:
Added higher-level sub and integer division. Made asm functions private.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r3825 |
r3829 |
|
| 10 | 10 | version(GNU) { |
|---|
| 11 | 11 | // GDC lies about its X86 support |
|---|
| 12 | | public import tango.math.impl.BignumNoAsm; |
|---|
| | 12 | private import tango.math.impl.BignumNoAsm; |
|---|
| 13 | 13 | } else version(D_InlineAsm_X86) { |
|---|
| 14 | | public import tango.math.impl.BignumX86; |
|---|
| | 14 | private import tango.math.impl.BignumX86; |
|---|
| 15 | 15 | } else { |
|---|
| 16 | | public import tango.math.impl.BignumNoAsm; |
|---|
| 17 | | } |
|---|
| 18 | | |
|---|
| 19 | | private: |
|---|
| 20 | | void itoaZeroPadded(char[] output, uint value, int radix = 10) { |
|---|
| 21 | | int x = output.length - 1; |
|---|
| 22 | | for( ; x>=0; --x) { |
|---|
| 23 | | output[x]= value % radix + '0'; |
|---|
| 24 | | value /= radix; |
|---|
| 25 | | } |
|---|
| 26 | | } |
|---|
| 27 | | |
|---|
| 28 | | void toHexZeroPadded(char[] output, uint value) { |
|---|
| 29 | | int x = output.length - 1; |
|---|
| 30 | | const char [] hexDigits = "0123456789ABCDEF"; |
|---|
| 31 | | for( ; x>=0; --x) { |
|---|
| 32 | | output[x] = hexDigits[value & 0xF]; |
|---|
| 33 | | value >>>= 4; |
|---|
| 34 | | } |
|---|
| | 16 | private import tango.math.impl.BignumNoAsm; |
|---|
| 35 | 17 | } |
|---|
| 36 | 18 | |
|---|
| 37 | 19 | public: |
|---|
| 38 | | |
|---|
| 39 | | // Returns the highest value of i for which left[i]!=right[i], |
|---|
| 40 | | // or 0 if left[]==right[] |
|---|
| 41 | | int lastDifferentDigit(uint [] left, uint [] right) |
|---|
| 42 | | { |
|---|
| 43 | | assert(left.length == right.length); |
|---|
| 44 | | for (int i=left.length; i>0; --i) { |
|---|
| 45 | | if (left[i]!=right[i]) return i; |
|---|
| 46 | | } |
|---|
| 47 | | return 0; |
|---|
| 48 | | } |
|---|
| 49 | | |
|---|
| 50 | 20 | // Converts a big uint to a hexadecimal string. |
|---|
| 51 | 21 | // |
|---|
| … | … | |
| 185 | 155 | } |
|---|
| 186 | 156 | |
|---|
| 187 | | private: |
|---|
| 188 | | // classic 'schoolbook' multiplication. |
|---|
| 189 | | void mulSimple(uint[] result, uint [] left, uint[] right) |
|---|
| 190 | | in { |
|---|
| 191 | | assert(result.length == left.length + right.length); |
|---|
| 192 | | assert(right.length>1); |
|---|
| 193 | | } |
|---|
| 194 | | body { |
|---|
| 195 | | result[left.length] = multibyteMul(result[0..left.length], left, right[0], 0); |
|---|
| 196 | | if (right.length>1) |
|---|
| 197 | | multibyteMultiplyAccumulate(result[1..$], left, right[1..$]); |
|---|
| 198 | | } |
|---|
| 199 | | |
|---|
| 200 | | // add two uints of possibly different lengths. Result must be as long |
|---|
| 201 | | // as the larger length. |
|---|
| 202 | | uint addSimple(uint [] result, uint [] left, uint [] right) |
|---|
| 203 | | in { |
|---|
| 204 | | assert(result.length == left.length); |
|---|
| 205 | | assert(left.length >= right.length); |
|---|
| 206 | | assert(right.length>0); |
|---|
| 207 | | } |
|---|
| 208 | | body { |
|---|
| 209 | | uint carry = multibyteAddSub!('+')(result[0..right.length], |
|---|
| 210 | | left[0..right.length], right, 0); |
|---|
| 211 | | if (right.length < left.length) { |
|---|
| 212 | | result[right.length..left.length] = left[right.length .. $]; |
|---|
| 213 | | carry = multibyteIncrementAssign!('+')(result[right.length..$], carry); |
|---|
| 214 | | } //else if (result.length==left.length+1) { result[$-1] = carry; carry=0; } |
|---|
| 215 | | return carry; |
|---|
| 216 | | } |
|---|
| 217 | | |
|---|
| 218 | | /* result must be larger than right. |
|---|
| 219 | | */ |
|---|
| 220 | | void simpleSubAssign(uint [] result, uint [] right) |
|---|
| 221 | | { |
|---|
| 222 | | assert(result.length > right.length); |
|---|
| 223 | | uint c = multibyteAddSub!('-')(result[0..right.length], result[0..right.length], right, 0); |
|---|
| 224 | | if (c) c = multibyteIncrementAssign!('-')(result[right.length .. $], c); |
|---|
| 225 | | assert(c==0); |
|---|
| 226 | | } |
|---|
| 227 | | |
|---|
| 228 | | void simpleAddAssign(uint [] result, uint [] right) |
|---|
| 229 | | { |
|---|
| 230 | | assert(result.length > right.length); |
|---|
| 231 | | uint c = multibyteAddSub!('+')(result[0..right.length], result[0..right.length], right, 0); |
|---|
| 232 | | if (c) c = multibyteIncrementAssign!('+')(result[right.length .. $], c); |
|---|
| 233 | | assert(c==0); |
|---|
| 234 | | } |
|---|
| 235 | | |
|---|
| 236 | | // Limits for when to switch between multiplication algorithms. |
|---|
| 237 | | const int CACHELIMIT = 8000; // Half the size of the data cache. |
|---|
| 238 | | |
|---|
| 239 | | /* Determine how much space is required for the temporaries |
|---|
| 240 | | * when performing a Karatsuba multiplication. |
|---|
| 241 | | */ |
|---|
| 242 | | uint karatsubaRequiredBuffSize(uint xlen) |
|---|
| 243 | | { |
|---|
| 244 | | return xlen <= KARATSUBALIMIT ? 0 : xlen * 2; |
|---|
| 245 | | } |
|---|
| 246 | | |
|---|
| 247 | | /* Sets result = x*y, using Karatsuba multiplication. |
|---|
| 248 | | * Valid only for balanced multiplies, and x must be longer than y. |
|---|
| 249 | | * ie 2*y.length > x.length >= y.length. |
|---|
| 250 | | * Params: |
|---|
| 251 | | * scratchbuff An array long enough to store all the temporaries. Will be destroyed. |
|---|
| 252 | | */ |
|---|
| 253 | | void mulKaratsuba(uint [] result, uint [] x, uint[] y, uint [] scratchbuff) |
|---|
| 254 | | { |
|---|
| 255 | | assert(result.length == x.length + y.length); |
|---|
| 256 | | assert(x.length >= y.length); |
|---|
| 257 | | if (x.length <= KARATSUBALIMIT) { |
|---|
| 258 | | return mulSimple(result, x, y); |
|---|
| 259 | | } |
|---|
| 260 | | // Karatsuba multiply uses the following result: |
|---|
| 261 | | // (Nx1 + x0)*(Ny1 + y0) = (N*N) x1y1 + x0y0 + N * mid |
|---|
| 262 | | // where mid = (x1+x0)*(y1+y0) - x1y1 - x0y0 |
|---|
| 263 | | // requiring 3 multiplies of length N, instead of 4. |
|---|
| 264 | | |
|---|
| 265 | | // half length, round up. |
|---|
| 266 | | uint half = (x.length >> 1) + (x.length & 1); |
|---|
| 267 | | assert(y.length>half, "Asymmetric Karatsuba"); |
|---|
| 268 | | |
|---|
| 269 | | uint [] x0 = x[0 .. half]; |
|---|
| 270 | | uint [] x1 = x[half .. $]; |
|---|
| 271 | | uint [] y0 = y[0 .. half]; |
|---|
| 272 | | uint [] y1 = y[half .. $]; |
|---|
| 273 | | uint [] xsum = result[0 .. half]; // initially use result to store temporaries |
|---|
| 274 | | uint [] ysum = result[half .. half*2]; |
|---|
| 275 | | uint [] mid = scratchbuff[0 .. half*2+1]; |
|---|
| 276 | | uint [] newscratchbuff = scratchbuff[half*2+2 .. $]; |
|---|
| 277 | | uint [] resultLow = result[0 .. x0.length + y0.length]; |
|---|
| 278 | | uint [] resultHigh = result[x0.length + y0.length .. $]; |
|---|
| 279 | | |
|---|
| 280 | | // Add the high and low parts of x and y. |
|---|
| 281 | | // This will generate carries of either 0 or 1. |
|---|
| 282 | | uint carry_x = addSimple(xsum, x0, x1); |
|---|
| 283 | | uint carry_y = addSimple(ysum, y0, y1); |
|---|
| 284 | | |
|---|
| 285 | | mulKaratsuba(mid[0..half*2], xsum, ysum, newscratchbuff); |
|---|
| 286 | | mid[half*2] = carry_x & carry_y; |
|---|
| 287 | | if (carry_x) simpleAddAssign(mid[half..$], ysum); |
|---|
| 288 | | if (carry_y) simpleAddAssign(mid[half..$], xsum); |
|---|
| 289 | | |
|---|
| 290 | | // Low half of result gets x0 * y0. High half gets x1 * y1 |
|---|
| 291 | | |
|---|
| 292 | | mulKaratsuba(resultLow, x0, y0, newscratchbuff); |
|---|
| 293 | | mid.simpleSubAssign(resultLow); |
|---|
| 294 | | mulKaratsuba(resultHigh, x1, y1, newscratchbuff); |
|---|
| 295 | | mid.simpleSubAssign(resultHigh); |
|---|
| 296 | | |
|---|
| 297 | | // result += MID |
|---|
| 298 | | result[half..$].simpleAddAssign(mid); |
|---|
| 299 | | } |
|---|
| 300 | | |
|---|
| 301 | 157 | public: |
|---|
| | 158 | |
|---|
| | 159 | /** General unsigned subtraction routine for bigints. |
|---|
| | 160 | * Sets result = x - y. If the result is negative, negative will be true. |
|---|
| | 161 | * |
|---|
| | 162 | * The length of y must not be larger than the length of x. |
|---|
| | 163 | */ |
|---|
| | 164 | uint [] biguintSubtract(uint[] x, uint[] y, bool *negative) |
|---|
| | 165 | { |
|---|
| | 166 | if (x.length == y.length) { |
|---|
| | 167 | // There's a possibility of cancellation, if x and y are almost equal. |
|---|
| | 168 | int last = lastDifferentDigit(x, y); |
|---|
| | 169 | uint [] result = new uint[last+1]; |
|---|
| | 170 | if (x[last] < y[last]) { // we know result is negative |
|---|
| | 171 | multibyteAddSub!('-')(result[0..last+1], y[0..last+1], x[0..last+1], 0); |
|---|
| | 172 | *negative = true; |
|---|
| | 173 | } else { // positive or zero result |
|---|
| | 174 | multibyteAddSub!('-')(result[0..last+1], x[0..last+1], y[0..last+1], 0); |
|---|
| | 175 | *negative = false; |
|---|
| | 176 | } |
|---|
| | 177 | return result; |
|---|
| | 178 | } |
|---|
| | 179 | // Lengths are different |
|---|
| | 180 | uint [] large, small; |
|---|
| | 181 | if (x.length < y.length) { |
|---|
| | 182 | *negative = true; |
|---|
| | 183 | large = y; small = x; |
|---|
| | 184 | // return biguintSubDifferentLength(y, x); |
|---|
| | 185 | } else { |
|---|
| | 186 | *negative = false; |
|---|
| | 187 | large = x; small = y; |
|---|
| | 188 | // return biguintSubDifferentLength(x, y); |
|---|
| | 189 | } |
|---|
| | 190 | // result.length will be equal to larger length, or could decrease by 1. |
|---|
| | 191 | |
|---|
| | 192 | uint [] result = new uint[large.length]; |
|---|
| | 193 | uint carry = multibyteAddSub!('-')(result[0..small.length], large[0..small.length], small, 0); |
|---|
| | 194 | result[small.length..$-1] = large[small.length..$]; |
|---|
| | 195 | if (carry) { |
|---|
| | 196 | multibyteIncrementAssign!('-')(result[small.length..$-1], carry); |
|---|
| | 197 | if (result[$-1]==0) return result[0..$-1]; |
|---|
| | 198 | } |
|---|
| | 199 | return result; |
|---|
| | 200 | } |
|---|
| | 201 | |
|---|
| | 202 | // return a+b |
|---|
| | 203 | uint [] biguintAdd(uint[] a, uint [] b) { |
|---|
| | 204 | uint [] x, y; |
|---|
| | 205 | if (a.length<b.length) { x = b; y = a; } else {x = a; y = b; } |
|---|
| | 206 | // now we know x.length > y.length |
|---|
| | 207 | // create result. add 1 in case it overflows |
|---|
| | 208 | uint [] result = new uint[x.length + 1]; |
|---|
| | 209 | |
|---|
| | 210 | uint carry = multibyteAddSub!('+')(result[0..y.length], x[0..y.length], y, 0); |
|---|
| | 211 | if (x.length != y.length){ |
|---|
| | 212 | result[y.length..$-1]= x[y.length..$]; |
|---|
| | 213 | carry = multibyteIncrementAssign!('+')(result[y.length..$-1], carry); |
|---|
| | 214 | } |
|---|
| | 215 | if (carry) { |
|---|
| | 216 | result[$-1] = carry; |
|---|
| | 217 | return result; |
|---|
| | 218 | } else return result[0..$-1]; |
|---|
| | 219 | } |
|---|
| | 220 | |
|---|
| | 221 | |
|---|
| | 222 | /** return x+y |
|---|
| | 223 | */ |
|---|
| | 224 | uint [] biguintAddInt(uint[] x, ulong y) |
|---|
| | 225 | { |
|---|
| | 226 | uint hi = cast(uint)(y >>> 32); |
|---|
| | 227 | uint lo = cast(uint)(y& 0xFFFF_FFFF); |
|---|
| | 228 | uint len = x.length; |
|---|
| | 229 | if (x.length < 2 && hi!=0) ++len; |
|---|
| | 230 | uint [] result = new uint[len+1]; |
|---|
| | 231 | result[0..x.length] = x[]; |
|---|
| | 232 | if (x.length < 2 && hi!=0) { result[1]=hi; hi=0; } |
|---|
| | 233 | uint carry = multibyteIncrementAssign!('+')(result[0..$-1], lo); |
|---|
| | 234 | if (hi!=0) carry += multibyteIncrementAssign!('+')(result[1..$-1], hi); |
|---|
| | 235 | if (carry) { |
|---|
| | 236 | result[$-1] = carry; |
|---|
| | 237 | return result; |
|---|
| | 238 | } else return result[0..$-1]; |
|---|
| | 239 | } |
|---|
| 302 | 240 | |
|---|
| 303 | 241 | /** General unsigned multiply routine for bigints. |
|---|
| … | … | |
| 373 | 311 | done += y.length; |
|---|
| 374 | 312 | } |
|---|
| 375 | | //delete scratchbuff; |
|---|
| | 313 | delete scratchbuff; |
|---|
| 376 | 314 | } else { |
|---|
| 377 | 315 | // Balanced. Use Karatsuba directly. |
|---|
| 378 | 316 | uint [] scratchbuff = new uint[karatsubaRequiredBuffSize(x.length)]; |
|---|
| 379 | 317 | mulKaratsuba(result, x, y, scratchbuff); |
|---|
| 380 | | // delete scratchbuff; |
|---|
| 381 | | } |
|---|
| 382 | | } |
|---|
| | 318 | delete scratchbuff; |
|---|
| | 319 | } |
|---|
| | 320 | } |
|---|
| | 321 | |
|---|
| | 322 | // return x/y |
|---|
| | 323 | uint[] biguintDivInt(uint [] x, uint y) { |
|---|
| | 324 | uint [] result = new uint[x.length]; |
|---|
| | 325 | if ((y&(-y))==y) { |
|---|
| | 326 | // perfect power of 2 |
|---|
| | 327 | uint b = 0; |
|---|
| | 328 | for (;y!=0; y>>=1) { |
|---|
| | 329 | ++b; |
|---|
| | 330 | } |
|---|
| | 331 | multibyteShr(result, x, b); |
|---|
| | 332 | } else { |
|---|
| | 333 | result[] = x[]; |
|---|
| | 334 | uint rem = multibyteDivAssign(result, y, 0); |
|---|
| | 335 | } |
|---|
| | 336 | if (result[$-1]==0 && result.length>1) { |
|---|
| | 337 | return result[0..$-1]; |
|---|
| | 338 | } else return result; |
|---|
| | 339 | } |
|---|
| | 340 | |
|---|
| | 341 | |
|---|
| | 342 | private: |
|---|
| | 343 | // ------------------------ |
|---|
| | 344 | // These in-place functions are only for internal use; they are incompatible |
|---|
| | 345 | // with COW. |
|---|
| | 346 | |
|---|
| | 347 | // Classic 'schoolbook' multiplication. |
|---|
| | 348 | void mulSimple(uint[] result, uint [] left, uint[] right) |
|---|
| | 349 | in { |
|---|
| | 350 | assert(result.length == left.length + right.length); |
|---|
| | 351 | assert(right.length>1); |
|---|
| | 352 | } |
|---|
| | 353 | body { |
|---|
| | 354 | result[left.length] = multibyteMul(result[0..left.length], left, right[0], 0); |
|---|
| | 355 | if (right.length>1) |
|---|
| | 356 | multibyteMultiplyAccumulate(result[1..$], left, right[1..$]); |
|---|
| | 357 | } |
|---|
| | 358 | |
|---|
| | 359 | |
|---|
| | 360 | // add two uints of possibly different lengths. Result must be as long |
|---|
| | 361 | // as the larger length. |
|---|
| | 362 | uint addSimple(uint [] result, uint [] left, uint [] right) |
|---|
| | 363 | in { |
|---|
| | 364 | assert(result.length == left.length); |
|---|
| | 365 | assert(left.length >= right.length); |
|---|
| | 366 | assert(right.length>0); |
|---|
| | 367 | } |
|---|
| | 368 | body { |
|---|
| | 369 | uint carry = multibyteAddSub!('+')(result[0..right.length], |
|---|
| | 370 | left[0..right.length], right, 0); |
|---|
| | 371 | if (right.length < left.length) { |
|---|
| | 372 | result[right.length..left.length] = left[right.length .. $]; |
|---|
| | 373 | carry = multibyteIncrementAssign!('+')(result[right.length..$], carry); |
|---|
| | 374 | } //else if (result.length==left.length+1) { result[$-1] = carry; carry=0; } |
|---|
| | 375 | return carry; |
|---|
| | 376 | } |
|---|
| | 377 | |
|---|
| | 378 | /* result must be larger than right. |
|---|
| | 379 | */ |
|---|
| | 380 | void simpleSubAssign(uint [] result, uint [] right) |
|---|
| | 381 | { |
|---|
| | 382 | assert(result.length > right.length); |
|---|
| | 383 | uint c = multibyteAddSub!('-')(result[0..right.length], result[0..right.length], right, 0); |
|---|
| | 384 | if (c) c = multibyteIncrementAssign!('-')(result[right.length .. $], c); |
|---|
| | 385 | assert(c==0); |
|---|
| | 386 | } |
|---|
| | 387 | |
|---|
| | 388 | |
|---|
| | 389 | void simpleAddAssign(uint [] result, uint [] right) |
|---|
| | 390 | { |
|---|
| | 391 | assert(result.length > right.length); |
|---|
| | 392 | uint c = multibyteAddSub!('+')(result[0..right.length], result[0..right.length], right, 0); |
|---|
| | 393 | if (c) c = multibyteIncrementAssign!('+')(result[right.length .. $], c); |
|---|
| | 394 | assert(c==0); |
|---|
| | 395 | } |
|---|
| | 396 | |
|---|
| | 397 | // Limits for when to switch between multiplication algorithms. |
|---|
| | 398 | const int CACHELIMIT = 8000; // Half the size of the data cache. |
|---|
| | 399 | |
|---|
| | 400 | /* Determine how much space is required for the temporaries |
|---|
| | 401 | * when performing a Karatsuba multiplication. |
|---|
| | 402 | */ |
|---|
| | 403 | uint karatsubaRequiredBuffSize(uint xlen) |
|---|
| | 404 | { |
|---|
| | 405 | return xlen <= KARATSUBALIMIT ? 0 : xlen * 2; |
|---|
| | 406 | } |
|---|
| | 407 | |
|---|
| | 408 | /* Sets result = x*y, using Karatsuba multiplication. |
|---|
| | 409 | * Valid only for balanced multiplies, and x must be longer than y. |
|---|
| | 410 | * ie 2*y.length > x.length >= y.length. |
|---|
| | 411 | * Params: |
|---|
| | 412 | * scratchbuff An array long enough to store all the temporaries. Will be destroyed. |
|---|
| | 413 | */ |
|---|
| | 414 | void mulKaratsuba(uint [] result, uint [] x, uint[] y, uint [] scratchbuff) |
|---|
| | 415 | { |
|---|
| | 416 | assert(result.length == x.length + y.length); |
|---|
| | 417 | assert(x.length >= y.length); |
|---|
| | 418 | if (x.length <= KARATSUBALIMIT) { |
|---|
| | 419 | return mulSimple(result, x, y); |
|---|
| | 420 | } |
|---|
| | 421 | // Karatsuba multiply uses the following result: |
|---|
| | 422 | // (Nx1 + x0)*(Ny1 + y0) = (N*N) x1y1 + x0y0 + N * mid |
|---|
| | 423 | // where mid = (x1+x0)*(y1+y0) - x1y1 - x0y0 |
|---|
| | 424 | // requiring 3 multiplies of length N, instead of 4. |
|---|
| | 425 | |
|---|
| | 426 | // half length, round up. |
|---|
| | 427 | uint half = (x.length >> 1) + (x.length & 1); |
|---|
| | 428 | assert(y.length>half, "Asymmetric Karatsuba"); |
|---|
| | 429 | |
|---|
| | 430 | uint [] x0 = x[0 .. half]; |
|---|
| | 431 | uint [] x1 = x[half .. $]; |
|---|
| | 432 | uint [] y0 = y[0 .. half]; |
|---|
| | 433 | uint [] y1 = y[half .. $]; |
|---|
| | 434 | uint [] xsum = result[0 .. half]; // initially use result to store temporaries |
|---|
| | 435 | uint [] ysum = result[half .. half*2]; |
|---|
| | 436 | uint [] mid = scratchbuff[0 .. half*2+1]; |
|---|
| | 437 | uint [] newscratchbuff = scratchbuff[half*2+2 .. $]; |
|---|
| | 438 | uint [] resultLow = result[0 .. x0.length + y0.length]; |
|---|
| | 439 | uint [] resultHigh = result[x0.length + y0.length .. $]; |
|---|
| | 440 | |
|---|
| | 441 | // Add the high and low parts of x and y. |
|---|
| | 442 | // This will generate carries of either 0 or 1. |
|---|
| | 443 | uint carry_x = addSimple(xsum, x0, x1); |
|---|
| | 444 | uint carry_y = addSimple(ysum, y0, y1); |
|---|
| | 445 | |
|---|
| | 446 | mulKaratsuba(mid[0..half*2], xsum, ysum, newscratchbuff); |
|---|
| | 447 | mid[half*2] = carry_x & carry_y; |
|---|
| | 448 | if (carry_x) simpleAddAssign(mid[half..$], ysum); |
|---|
| | 449 | if (carry_y) simpleAddAssign(mid[half..$], xsum); |
|---|
| | 450 | |
|---|
| | 451 | // Low half of result gets x0 * y0. High half gets x1 * y1 |
|---|
| | 452 | |
|---|
| | 453 | mulKaratsuba(resultLow, x0, y0, newscratchbuff); |
|---|
| | 454 | mid.simpleSubAssign(resultLow); |
|---|
| | 455 | mulKaratsuba(resultHigh, x1, y1, newscratchbuff); |
|---|
| | 456 | mid.simpleSubAssign(resultHigh); |
|---|
| | 457 | |
|---|
| | 458 | // result += MID |
|---|
| | 459 | result[half..$].simpleAddAssign(mid); |
|---|
| | 460 | } |
|---|
| | 461 | |
|---|
| | 462 | private: |
|---|
| | 463 | void itoaZeroPadded(char[] output, uint value, int radix = 10) { |
|---|
| | 464 | int x = output.length - 1; |
|---|
| | 465 | for( ; x>=0; --x) { |
|---|
| | 466 | output[x]= value % radix + '0'; |
|---|
| | 467 | value /= radix; |
|---|
| | 468 | } |
|---|
| | 469 | } |
|---|
| | 470 | |
|---|
| | 471 | void toHexZeroPadded(char[] output, uint value) { |
|---|
| | 472 | int x = output.length - 1; |
|---|
| | 473 | const char [] hexDigits = "0123456789ABCDEF"; |
|---|
| | 474 | for( ; x>=0; --x) { |
|---|
| | 475 | output[x] = hexDigits[value & 0xF]; |
|---|
| | 476 | value >>>= 4; |
|---|
| | 477 | } |
|---|
| | 478 | } |
|---|
| | 479 | |
|---|
| | 480 | private: |
|---|
| | 481 | |
|---|
| | 482 | // Returns the highest value of i for which left[i]!=right[i], |
|---|
| | 483 | // or 0 if left[]==right[] |
|---|
| | 484 | int lastDifferentDigit(uint [] left, uint [] right) |
|---|
| | 485 | { |
|---|
| | 486 | assert(left.length == right.length); |
|---|
| | 487 | for (int i=left.length-1; i>0; --i) { |
|---|
| | 488 | if (left[i]!=right[i]) return i; |
|---|
| | 489 | } |
|---|
| | 490 | return 0; |
|---|
| | 491 | } |
|---|
| | 492 | |
|---|
Download in other formats:
|
 |