| 1 |
module etc.bigint.bigint_int; |
|---|
| 2 |
import etc.bigint.exception; |
|---|
| 3 |
import etc.bigint.multiply; |
|---|
| 4 |
import etc.bigint.radix; |
|---|
| 5 |
private import std.c.stdlib; |
|---|
| 6 |
private import std.math; |
|---|
| 7 |
private import std.string; |
|---|
| 8 |
|
|---|
| 9 |
/* |
|---|
| 10 |
|
|---|
| 11 |
Copyright (c) 2004, Arcane Jill |
|---|
| 12 |
|
|---|
| 13 |
All rights reserved. Intellectual Property Me Arse! |
|---|
| 14 |
|
|---|
| 15 |
Redistribution and use in source and binary forms, with or without modification, are permitted |
|---|
| 16 |
provided that the following conditions are met: |
|---|
| 17 |
|
|---|
| 18 |
* Redistributions of source code must retain the above copyright notice, the phrase |
|---|
| 19 |
"Intellectual Property Me Arse!", this list of conditions, and the following disclaimer. |
|---|
| 20 |
* Redistributions in binary form must reproduce the above copyright notice, the phrase |
|---|
| 21 |
"Intellectual Property Me Arse!", this list of conditions and the following disclaimer |
|---|
| 22 |
in the documentation and/or other materials provided with the distribution. |
|---|
| 23 |
* The name Arcane Jill may not be used to endorse or promote products derived from this |
|---|
| 24 |
software without specific prior written permission. |
|---|
| 25 |
|
|---|
| 26 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS |
|---|
| 27 |
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
|---|
| 28 |
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER, |
|---|
| 29 |
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|---|
| 30 |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|---|
| 31 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED, AND ON ANY |
|---|
| 32 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
|---|
| 33 |
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
|---|
| 34 |
OF SUCH DAMAGE. |
|---|
| 35 |
|
|---|
| 36 |
*/ |
|---|
| 37 |
|
|---|
| 38 |
class Int |
|---|
| 39 |
{ |
|---|
| 40 |
unittest |
|---|
| 41 |
{ |
|---|
| 42 |
Int a,b,c,d; |
|---|
| 43 |
|
|---|
| 44 |
//------------------------------------------ |
|---|
| 45 |
// Test comparisons |
|---|
| 46 |
a = new Int(0xAAAAAAAA); |
|---|
| 47 |
b = new Int(0xAAAAAAAA); |
|---|
| 48 |
c = new Int(0xCCCCCCCC); |
|---|
| 49 |
d = new Int("0x00000001AAAAAAAA"); |
|---|
| 50 |
assert(a == b); |
|---|
| 51 |
assert(a < c); |
|---|
| 52 |
assert(c > a); |
|---|
| 53 |
assert(a < d); |
|---|
| 54 |
assert(d > a); |
|---|
| 55 |
d = new Int(-1); |
|---|
| 56 |
assert(d < a); |
|---|
| 57 |
|
|---|
| 58 |
//------------------------------------------ |
|---|
| 59 |
// Test add and subtract |
|---|
| 60 |
a = b + c; |
|---|
| 61 |
d = new Int("0x0000000177777776"); |
|---|
| 62 |
assert(a == d); |
|---|
| 63 |
assert(a - b == c); |
|---|
| 64 |
c = -d; |
|---|
| 65 |
assert(c+d == 0); |
|---|
| 66 |
|
|---|
| 67 |
//------------------------------------------ |
|---|
| 68 |
// Test multiply and divide for small values |
|---|
| 69 |
a = new Int(0x11111111); |
|---|
| 70 |
a = -a; |
|---|
| 71 |
b = a * a; |
|---|
| 72 |
c = new Int("0x0123456787654321"); |
|---|
| 73 |
assert(b == c); |
|---|
| 74 |
b = b / a; |
|---|
| 75 |
assert(b == a); |
|---|
| 76 |
a = new Int(22); |
|---|
| 77 |
assert(a / 7 == 3); |
|---|
| 78 |
assert(a % 7 == 1); |
|---|
| 79 |
assert(a / -7 == -3); |
|---|
| 80 |
assert(a % -7 == 1); |
|---|
| 81 |
a = -a; |
|---|
| 82 |
assert(a / 7 == -3); |
|---|
| 83 |
assert(a % 7 == -1); |
|---|
| 84 |
assert(a / -7 == 3); |
|---|
| 85 |
assert(a % -7 == -1); |
|---|
| 86 |
a = -a; |
|---|
| 87 |
b = new Int(7); |
|---|
| 88 |
c = -b; |
|---|
| 89 |
assert(divMod(a, b, d, Round.TOWARD_MINUS_INFINITY) == 3); |
|---|
| 90 |
assert(d == 1); |
|---|
| 91 |
assert(divMod(a, c, d, Round.TOWARD_MINUS_INFINITY) == -4); |
|---|
| 92 |
assert(d == -6); |
|---|
| 93 |
a = -a; |
|---|
| 94 |
assert(divMod(a, b, d, Round.TOWARD_MINUS_INFINITY) == -4); |
|---|
| 95 |
assert(d == 6); |
|---|
| 96 |
assert(divMod(a, c, d, Round.TOWARD_MINUS_INFINITY) == 3); |
|---|
| 97 |
assert(d == -1); |
|---|
| 98 |
|
|---|
| 99 |
//------------------------------------------ |
|---|
| 100 |
// Test multiply and divide for large values |
|---|
| 101 |
a = new Int("0x0111111111111111"); |
|---|
| 102 |
b = a * a; |
|---|
| 103 |
c = new Int("0x000123456789ABCDEFEDCBA987654321"); |
|---|
| 104 |
assert(b == c); |
|---|
| 105 |
b = b / a; |
|---|
| 106 |
assert(b == a); |
|---|
| 107 |
|
|---|
| 108 |
//------------------------------------------ |
|---|
| 109 |
// Test binary operations |
|---|
| 110 |
a = new Int("0x1234567812345678"); |
|---|
| 111 |
uint n = a & 0xFFFFu; |
|---|
| 112 |
assert(n == 0x5678); |
|---|
| 113 |
b = a & new Int(0xFF00FF); |
|---|
| 114 |
assert(b == new Int(0x340078)); |
|---|
| 115 |
c = a | 0xFFFF; |
|---|
| 116 |
assert(c == new Int("0x123456781234FFFF")); |
|---|
| 117 |
d = a ^ 0xFFFFFFFF; |
|---|
| 118 |
assert (d == new Int("0x12345678EDCBA987")); |
|---|
| 119 |
c = d & -1; |
|---|
| 120 |
assert(c == d); |
|---|
| 121 |
c = ~d; |
|---|
| 122 |
assert((c ^ (-1)) == d); |
|---|
| 123 |
|
|---|
| 124 |
//------------------------------------------ |
|---|
| 125 |
// Test shift left and shift right |
|---|
| 126 |
a = new Int(0x12345678); |
|---|
| 127 |
b = a << 40; |
|---|
| 128 |
c = new Int("0x000000123456780000000000"); |
|---|
| 129 |
assert(b == c); |
|---|
| 130 |
d = c << -40; |
|---|
| 131 |
assert(d == a); |
|---|
| 132 |
d = c >>> 40; |
|---|
| 133 |
assert(d == a); |
|---|
| 134 |
c = -c; |
|---|
| 135 |
a = -a; |
|---|
| 136 |
d = c << -40; |
|---|
| 137 |
assert(d == a); |
|---|
| 138 |
try |
|---|
| 139 |
{ |
|---|
| 140 |
d = c >>> 40; |
|---|
| 141 |
} |
|---|
| 142 |
catch (IntException) |
|---|
| 143 |
{ |
|---|
| 144 |
b = ZERO; |
|---|
| 145 |
} |
|---|
| 146 |
assert(b == 0); |
|---|
| 147 |
d = c >>> 0; |
|---|
| 148 |
assert(c == d); |
|---|
| 149 |
|
|---|
| 150 |
//------------------------------------------ |
|---|
| 151 |
// Test the array-like functions |
|---|
| 152 |
|
|---|
| 153 |
a = new Int("0xFEDCBA98_76543210_00000000_00000000_FEDCBA98_76543210"); |
|---|
| 154 |
assert(a[1] == 0xFEDCBA98); |
|---|
| 155 |
assert(a[3000] == 0); |
|---|
| 156 |
assert(a[0..2] == a[4..6]); |
|---|
| 157 |
assert(a[100..115] == a[200..215]); |
|---|
| 158 |
assert(a[0..4] == a[4..8]); |
|---|
| 159 |
|
|---|
| 160 |
//------------------------------------------ |
|---|
| 161 |
// Test formatting |
|---|
| 162 |
|
|---|
| 163 |
a = new Int(123); |
|---|
| 164 |
assert(a.format(10, 0, 0, false, SignMode.NORMAL) == "123"); |
|---|
| 165 |
assert(a.format(10, 0, 0, false, SignMode.MINUS_SPACE_PLUS) == "+123"); |
|---|
| 166 |
assert(a.format(10, 0, 0, true, SignMode.NORMAL) == "123"); |
|---|
| 167 |
assert(a.format(10, 0, 2, false, SignMode.NORMAL) == "1_23"); |
|---|
| 168 |
assert(a.format(10, 5, 0, false, SignMode.NORMAL) == " 123"); |
|---|
| 169 |
assert(a.format(10, 5, 0, false, SignMode.MINUS_SPACE_PLUS) == " +123"); |
|---|
| 170 |
assert(a.format(10, 5, 0, true, SignMode.NORMAL) == "00123"); |
|---|
| 171 |
assert(a.format(10, 5, 0, true, SignMode.MINUS_SPACE_PLUS) == "+0123"); |
|---|
| 172 |
assert(a.format(10, 5, 2, false, SignMode.NORMAL) == " 1_23"); |
|---|
| 173 |
a = -a; |
|---|
| 174 |
assert(a.format(10, 5, 0, false, SignMode.NORMAL) == " -123"); |
|---|
| 175 |
assert(a.format(10, 5, 0, true, SignMode.NORMAL) == "-0123"); |
|---|
| 176 |
assert(a.format(10, 5, 2, false, SignMode.NORMAL) == "-1_23"); |
|---|
| 177 |
|
|---|
| 178 |
a = new Int("123456"); |
|---|
| 179 |
assert(a.toString() == "123456"); |
|---|
| 180 |
a = new Int("0x123456"); |
|---|
| 181 |
assert(a.toHexString() == "123456"); |
|---|
| 182 |
|
|---|
| 183 |
a = new Int("0"); |
|---|
| 184 |
assert (a.toString == "0"); |
|---|
| 185 |
assert (ZERO.toString == "0"); |
|---|
| 186 |
assert (a == ZERO); |
|---|
| 187 |
assert (a == new Int(0)); |
|---|
| 188 |
} |
|---|
| 189 |
|
|---|
| 190 |
invariant |
|---|
| 191 |
{ |
|---|
| 192 |
if (d) |
|---|
| 193 |
{ |
|---|
| 194 |
uint n = d.length; |
|---|
| 195 |
assert(n >= 2); // array must be sufficiently large (2 uints) |
|---|
| 196 |
int s = d[n-1]; |
|---|
| 197 |
assert((s == 0) || (s == -1)); // sign field may not contain rubbish |
|---|
| 198 |
if (n>2) |
|---|
| 199 |
{ |
|---|
| 200 |
assert(d[n-2] != s); // array must be minimal |
|---|
| 201 |
} |
|---|
| 202 |
} |
|---|
| 203 |
} |
|---|
| 204 |
|
|---|
| 205 |
public |
|---|
| 206 |
{ |
|---|
| 207 |
|
|---|
| 208 |
// -------- Constants -------- |
|---|
| 209 |
|
|---|
| 210 |
enum Round { TOWARD_ZERO, TOWARD_INFINITY, TOWARD_MINUS_INFINITY } |
|---|
| 211 |
|
|---|
| 212 |
static |
|---|
| 213 |
{ |
|---|
| 214 |
Int ZERO, ONE, TWO, MINUS_ONE; |
|---|
| 215 |
} |
|---|
| 216 |
|
|---|
| 217 |
static this() |
|---|
| 218 |
{ |
|---|
| 219 |
ZERO = new Int(0); |
|---|
| 220 |
ONE = new Int(1); |
|---|
| 221 |
TWO = new Int(2); |
|---|
| 222 |
MINUS_ONE = new Int(-1); |
|---|
| 223 |
} |
|---|
| 224 |
|
|---|
| 225 |
// -------- Constructors -------- |
|---|
| 226 |
|
|---|
| 227 |
// Construct from an int |
|---|
| 228 |
this(int n) |
|---|
| 229 |
{ |
|---|
| 230 |
d.length = 2; |
|---|
| 231 |
d[0] = n; |
|---|
| 232 |
d[1] = n < 0 ? -1U : 0; |
|---|
| 233 |
} |
|---|
| 234 |
|
|---|
| 235 |
static Int opCall(int n) { return new Int(n); } |
|---|
| 236 |
|
|---|
| 237 |
// Construct from a uint |
|---|
| 238 |
this(uint n) |
|---|
| 239 |
{ |
|---|
| 240 |
d.length = 2; |
|---|
| 241 |
d[0] = n; |
|---|
| 242 |
} |
|---|
| 243 |
|
|---|
| 244 |
static Int opCall(uint n) { return new Int(n); } |
|---|
| 245 |
|
|---|
| 246 |
// Construct from a long |
|---|
| 247 |
this(long n) |
|---|
| 248 |
{ |
|---|
| 249 |
d.length = 3; |
|---|
| 250 |
*(cast(ulong*)d) = n; |
|---|
| 251 |
d[2] = n < 0 ? -1U : 0; |
|---|
| 252 |
minimize(this); |
|---|
| 253 |
} |
|---|
| 254 |
|
|---|
| 255 |
static Int opCall(long n) { return new Int(n); } |
|---|
| 256 |
|
|---|
| 257 |
// Construct from a ulong |
|---|
| 258 |
this(ulong n) |
|---|
| 259 |
{ |
|---|
| 260 |
d.length = 3; |
|---|
| 261 |
*(cast(ulong*)d) = n; |
|---|
| 262 |
minimize(this); |
|---|
| 263 |
} |
|---|
| 264 |
|
|---|
| 265 |
static Int opCall(ulong n) { return new Int(n); } |
|---|
| 266 |
|
|---|
| 267 |
// Construct from a float |
|---|
| 268 |
this(float x) |
|---|
| 269 |
{ |
|---|
| 270 |
this(cast(real) x); |
|---|
| 271 |
} |
|---|
| 272 |
|
|---|
| 273 |
static Int opCall(float x) { return new Int(x); } |
|---|
| 274 |
|
|---|
| 275 |
// Construct from a double |
|---|
| 276 |
this(double x) |
|---|
| 277 |
{ |
|---|
| 278 |
this(cast(real) x); |
|---|
| 279 |
} |
|---|
| 280 |
|
|---|
| 281 |
static Int opCall(double x) { return new Int(x); } |
|---|
| 282 |
|
|---|
| 283 |
// Construct from a real |
|---|
| 284 |
this(real x) |
|---|
| 285 |
{ |
|---|
| 286 |
uint i; |
|---|
| 287 |
d.length = 4; |
|---|
| 288 |
bool sign = (x < 0); |
|---|
| 289 |
if (sign) x = -x; |
|---|
| 290 |
while (x > 0) |
|---|
| 291 |
{ |
|---|
| 292 |
real xq = floor(x / 4294967296.0); |
|---|
| 293 |
real xr = x - (xq * 4294967296.0); |
|---|
| 294 |
d[i++] = cast(uint) xr; |
|---|
| 295 |
if (i == d.length-1) d.length = d.length << 1; |
|---|
| 296 |
x = xq; |
|---|
| 297 |
} |
|---|
| 298 |
if (sign) |
|---|
| 299 |
{ |
|---|
| 300 |
bigintLLNeg(d, d, d.length); |
|---|
| 301 |
} |
|---|
| 302 |
minimize(this); |
|---|
| 303 |
} |
|---|
| 304 |
|
|---|
| 305 |
static Int opCall(real x) { return new Int(x); } |
|---|
| 306 |
|
|---|
| 307 |
// Construct from a string. |
|---|
| 308 |
this(char[] s) |
|---|
| 309 |
{ |
|---|
| 310 |
this(s, uint.max); |
|---|
| 311 |
} |
|---|
| 312 |
|
|---|
| 313 |
static Int opCall(char[] s) { return new Int(s); } |
|---|
| 314 |
|
|---|
| 315 |
this(char[] s, uint radix) |
|---|
| 316 |
{ |
|---|
| 317 |
bool isNegative = false; |
|---|
| 318 |
if (s.length > 1) |
|---|
| 319 |
{ |
|---|
| 320 |
if (s[0] == '+') |
|---|
| 321 |
{ |
|---|
| 322 |
s = s[1..s.length]; |
|---|
| 323 |
} |
|---|
| 324 |
else if (s[0] == '-') |
|---|
| 325 |
{ |
|---|
| 326 |
s = s[1..s.length]; |
|---|
| 327 |
isNegative = true; |
|---|
| 328 |
} |
|---|
| 329 |
} |
|---|
| 330 |
d = bigintFromString(s, radix); |
|---|
| 331 |
|
|---|
| 332 |
uint len = bigintLLMinimize(d, d.length); |
|---|
| 333 |
if (len == 0) |
|---|
| 334 |
{ |
|---|
| 335 |
d.length = 2; |
|---|
| 336 |
d[] = isNegative ? -1U : 0; |
|---|
| 337 |
} |
|---|
| 338 |
else |
|---|
| 339 |
{ |
|---|
| 340 |
d.length = len+1; |
|---|
| 341 |
} |
|---|
| 342 |
if (isNegative) |
|---|
| 343 |
{ |
|---|
| 344 |
bigintLLNeg(d, d, d.length); |
|---|
| 345 |
minimize(this); |
|---|
| 346 |
} |
|---|
| 347 |
} |
|---|
| 348 |
|
|---|
| 349 |
static Int opCall(char[] s, uint radix) { return new Int(s, radix); } |
|---|
| 350 |
|
|---|
| 351 |
// Construct from a uint array. This copies by value, not by reference; |
|---|
| 352 |
this(uint[] x, bool isNegative) |
|---|
| 353 |
{ |
|---|
| 354 |
d.length = x.length + 1; |
|---|
| 355 |
d[0..x.length] = x[0..x.length]; |
|---|
| 356 |
d[x.length] = isNegative ? -1U : 0; |
|---|
| 357 |
minimize(this); |
|---|
| 358 |
} |
|---|
| 359 |
|
|---|
| 360 |
static Int opCall(uint[] x, bool isNegative) { return new Int(x, isNegative); } |
|---|
| 361 |
|
|---|
| 362 |
// -------- Conversions -------- |
|---|
| 363 |
|
|---|
| 364 |
override |
|---|
| 365 |
{ |
|---|
| 366 |
char[] toString() |
|---|
| 367 |
out(s) |
|---|
| 368 |
{ |
|---|
| 369 |
assert(this == new Int(s)); |
|---|
| 370 |
} |
|---|
| 371 |
body |
|---|
| 372 |
{ |
|---|
| 373 |
return format(10, 0, 0, false, SignMode.NORMAL); |
|---|
| 374 |
} |
|---|
| 375 |
} |
|---|
| 376 |
|
|---|
| 377 |
char[] toHexString() |
|---|
| 378 |
out(s) |
|---|
| 379 |
{ |
|---|
| 380 |
assert(this == new Int(s,16)); |
|---|
| 381 |
} |
|---|
| 382 |
body |
|---|
| 383 |
{ |
|---|
| 384 |
return format(16, 0, 8, false, SignMode.NORMAL); |
|---|
| 385 |
} |
|---|
| 386 |
|
|---|
| 387 |
int toInt() |
|---|
| 388 |
{ |
|---|
| 389 |
if (isInt()) return d[0]; |
|---|
| 390 |
return (sign) ? int.min : int.max; |
|---|
| 391 |
} |
|---|
| 392 |
|
|---|
| 393 |
uint toUint() |
|---|
| 394 |
{ |
|---|
| 395 |
if (isUint()) return d[0]; |
|---|
| 396 |
return uint.max; |
|---|
| 397 |
} |
|---|
| 398 |
|
|---|
| 399 |
long toLong() |
|---|
| 400 |
{ |
|---|
| 401 |
if (isLong()) |
|---|
| 402 |
{ |
|---|
| 403 |
ulong lo = d[0]; |
|---|
| 404 |
ulong hi = d[1]; |
|---|
| 405 |
return (hi << 32) | lo; |
|---|
| 406 |
} |
|---|
| 407 |
return (sign) ? long.min : long.max; |
|---|
| 408 |
} |
|---|
| 409 |
|
|---|
| 410 |
ulong toUlong() |
|---|
| 411 |
{ |
|---|
| 412 |
if (isUlong()) |
|---|
| 413 |
{ |
|---|
| 414 |
ulong lo = d[0]; |
|---|
| 415 |
ulong hi = d[1]; |
|---|
| 416 |
return (hi << 32) | lo; |
|---|
| 417 |
} |
|---|
| 418 |
return ulong.max; |
|---|
| 419 |
} |
|---|
| 420 |
|
|---|
| 421 |
float toFloat() |
|---|
| 422 |
{ |
|---|
| 423 |
return toReal(); |
|---|
| 424 |
} |
|---|
| 425 |
|
|---|
| 426 |
double toDouble() |
|---|
| 427 |
{ |
|---|
| 428 |
return toReal(); |
|---|
| 429 |
} |
|---|
| 430 |
|
|---|
| 431 |
real toReal() |
|---|
| 432 |
{ |
|---|
| 433 |
if (sign) return -((-this).toReal()); |
|---|
| 434 |
real r = 0; |
|---|
| 435 |
for (uint i=0; i<end; ++i) |
|---|
| 436 |
{ |
|---|
| 437 |
r *= 4294967296.0; |
|---|
| 438 |
r += d[i]; |
|---|
| 439 |
} |
|---|
| 440 |
return r; |
|---|
| 441 |
} |
|---|
| 442 |
|
|---|
| 443 |
// -------- Tests -------- |
|---|
| 444 |
|
|---|
| 445 |
bool isInt() |
|---|
| 446 |
{ |
|---|
| 447 |
if (d.length > 2) return false; |
|---|
| 448 |
if (sign) |
|---|
| 449 |
{ |
|---|
| 450 |
return (d[0] >= 0x80000000); |
|---|
| 451 |
} |
|---|
| 452 |
else |
|---|
| 453 |
{ |
|---|
| 454 |
return (d[0] < 0x80000000); |
|---|
| 455 |
} |
|---|
| 456 |
} |
|---|
| 457 |
|
|---|
| 458 |
bool isUint() |
|---|
| 459 |
{ |
|---|
| 460 |
if (sign) return false; |
|---|
| 461 |
return (d.length == 2); |
|---|
| 462 |
} |
|---|
| 463 |
|
|---|
| 464 |
bool isLong() |
|---|
| 465 |
{ |
|---|
| 466 |
if (d.length > 3) return false; |
|---|
| 467 |
if (sign) |
|---|
| 468 |
{ |
|---|
| 469 |
return (d[d.length-2] >= 0x80000000); |
|---|
| 470 |
} |
|---|
| 471 |
else |
|---|
| 472 |
{ |
|---|
| 473 |
return (d[d.length-2] < 0x80000000); |
|---|
| 474 |
} |
|---|
| 475 |
} |
|---|
| 476 |
|
|---|
| 477 |
bool isUlong() |
|---|
| 478 |
{ |
|---|
| 479 |
if (sign) return false; |
|---|
| 480 |
return (d.length <= 3); |
|---|
| 481 |
} |
|---|
| 482 |
|
|---|
| 483 |
override |
|---|
| 484 |
{ |
|---|
| 485 |
int /*I wish this was bool*/ opEquals(Object obj) |
|---|
| 486 |
{ |
|---|
| 487 |
Int y = cast(Int) obj; |
|---|
| 488 |
assert(y); |
|---|
| 489 |
return d == y.d; |
|---|
| 490 |
} |
|---|
| 491 |
} |
|---|
| 492 |
|
|---|
| 493 |
int /*I wish this was bool*/ opEquals(int n) |
|---|
| 494 |
{ |
|---|
| 495 |
return isInt() ? (n == d[0]) : 0; |
|---|
| 496 |
} |
|---|
| 497 |
|
|---|
| 498 |
int /*I wish this was bool*/ opEquals(uint n) |
|---|
| 499 |
{ |
|---|
| 500 |
return isUint() ? (n == d[0]) : 0; |
|---|
| 501 |
} |
|---|
| 502 |
|
|---|
| 503 |
override |
|---|
| 504 |
{ |
|---|
| 505 |
int opCmp(Object obj) |
|---|
| 506 |
{ |
|---|
| 507 |
Int y = cast(Int) obj; |
|---|
| 508 |
assert(y); |
|---|
| 509 |
|
|---|
| 510 |
Int x = this; |
|---|
| 511 |
if (x === y) return 0; |
|---|
| 512 |
int xSign = x.sign; |
|---|
| 513 |
int ySign = y.sign; |
|---|
| 514 |
if (xSign < ySign) return -1; |
|---|
| 515 |
if (xSign > ySign) return 1; |
|---|
| 516 |
|
|---|
| 517 |
int r; |
|---|
| 518 |
int n = x.d.length; |
|---|
| 519 |
if (x.d.length > y.d.length) |
|---|
| 520 |
{ |
|---|
| 521 |
n = y.d.length; |
|---|
| 522 |
r = bigintLLCmpAll(&x.d[y.d.length], y.sign, x.d.length - y.d.length); |
|---|
| 523 |
if (r < 0) return -1; |
|---|
| 524 |
if (r > 0) return 1; |
|---|
| 525 |
} |
|---|
| 526 |
if (x.d.length < y.d.length) |
|---|
| 527 |
{ |
|---|
| 528 |
r = bigintLLCmpAll(x.sign, &y.d[x.d.length], y.d.length - x.d.length); |
|---|
| 529 |
if (r < 0) return -1; |
|---|
| 530 |
if (r > 0) return 1; |
|---|
| 531 |
} |
|---|
| 532 |
r = bigintLLCmp(x.d, y.d, n); |
|---|
| 533 |
if (r < 0) return -1; |
|---|
| 534 |
if (r > 0) return 1; |
|---|
| 535 |
return 0; |
|---|
| 536 |
} |
|---|
| 537 |
} |
|---|
| 538 |
|
|---|
| 539 |
int opCmp(int y) |
|---|
| 540 |
{ |
|---|
| 541 |
if (isInt()) |
|---|
| 542 |
{ |
|---|
| 543 |
int x = d[0]; |
|---|
| 544 |
if (x == y) return 0; |
|---|
| 545 |
return (x < y) ? -1 : 1; |
|---|
| 546 |
} |
|---|
| 547 |
else |
|---|
| 548 |
{ |
|---|
| 549 |
return opCmp(new Int(y)); |
|---|
| 550 |
} |
|---|
| 551 |
} |
|---|
| 552 |
|
|---|
| 553 |
int opCmp(uint y) |
|---|
| 554 |
{ |
|---|
| 555 |
if (isUint()) |
|---|
| 556 |
{ |
|---|
| 557 |
uint x = d[0]; |
|---|
| 558 |
if (x == y) return 0; |
|---|
| 559 |
return (x < y) ? -1 : 1; |
|---|
| 560 |
} |
|---|
| 561 |
else |
|---|
| 562 |
{ |
|---|
| 563 |
return opCmp(new Int(y)); |
|---|
| 564 |
} |
|---|
| 565 |
} |
|---|
| 566 |
|
|---|
| 567 |
// -------- Addition -------- |
|---|
| 568 |
|
|---|
| 569 |
Int opAdd(Int y) |
|---|
| 570 |
{ |
|---|
| 571 |
if (y.equalsZero()) return this; |
|---|
| 572 |
|
|---|
| 573 |
Int x = this; |
|---|
| 574 |
if (x.d.length < y.d.length) |
|---|
| 575 |
{ |
|---|
| 576 |
x = y; |
|---|
| 577 |
y = this; |
|---|
| 578 |
} |
|---|
| 579 |
Int r = new Int; |
|---|
| 580 |
r.d.length = x.d.length + 1; |
|---|
| 581 |
uint carry = bigintLLAdd(r.d, x.d, y.d, y.d.length); |
|---|
| 582 |
if (x.d.length > y.d.length) |
|---|
| 583 |
{ |
|---|
| 584 |
carry = bigintLLIncV(&r.d[y.d.length], &x.d[y.d.length], y.sign, carry, x.d.length-y.d.length); |
|---|
| 585 |
} |
|---|
| 586 |
r.d[x.d.length] = x.d[x.d.length-1] + y.d[y.d.length-1] + carry; |
|---|
| 587 |
return minimize(r); |
|---|
| 588 |
} |
|---|
| 589 |
|
|---|
| 590 |
Int opAdd(int y) |
|---|
| 591 |
{ |
|---|
| 592 |
if (y == 0) return this; |
|---|
| 593 |
|
|---|
| 594 |
Int x = this; |
|---|
| 595 |
Int r = new Int; |
|---|
| 596 |
r.d.length = x.d.length + 1; |
|---|
| 597 |
|
|---|
| 598 |
ulong t = x.d[0] + cast(ulong) cast(uint) y; |
|---|
| 599 |
r.d[0] = t; |
|---|
| 600 |
uint carry = t > 0xFFFFFFFF; |
|---|
| 601 |
|
|---|
| 602 |
carry = bigintLLIncV(&r.d[1], &x.d[1], cast(uint) (y<0?-1:0), carry, x.d.length-1); |
|---|
| 603 |
r.d[x.d.length] = x.d[x.d.length-1] + (y<0?-1:0) + carry; |
|---|
| 604 |
return minimize(r); |
|---|
| 605 |
} |
|---|
| 606 |
|
|---|
| 607 |
Int opAdd(uint y) |
|---|
| 608 |
{ |
|---|
| 609 |
if (y == 0) return this; |
|---|
| 610 |
uint carry; |
|---|
| 611 |
|
|---|
| 612 |
Int x = this; |
|---|
| 613 |
Int r = new Int; |
|---|
| 614 |
r.d.length = x.d.length + 1; |
|---|
| 615 |
carry = bigintLLInc(r.d, x.d, y, x.d.length); |
|---|
| 616 |
r.d[x.d.length] = x.d[x.d.length-1] + carry; |
|---|
| 617 |
return minimize(r); |
|---|
| 618 |
} |
|---|
| 619 |
|
|---|
| 620 |
// -------- Subtraction -------- |
|---|
| 621 |
|
|---|
| 622 |
Int opSub(Int y) |
|---|
| 623 |
{ |
|---|
| 624 |
if (y.equalsZero()) return this; |
|---|
| 625 |
bool neg = false; |
|---|
| 626 |
|
|---|
| 627 |
Int x = this; |
|---|
| 628 |
if (x.d.length < y.d.length) |
|---|
| 629 |
{ |
|---|
| 630 |
x = y; |
|---|
| 631 |
y = this; |
|---|
| 632 |
neg = true; |
|---|
| 633 |
} |
|---|
| 634 |
Int r = new Int; |
|---|
| 635 |
r.d.length = x.d.length + 1; |
|---|
| 636 |
|
|---|
| 637 |
uint carry = bigintLLSub(r.d, x.d, y.d, y.d.length); |
|---|
| 638 |
if (x.d.length > y.d.length) |
|---|
| 639 |
{ |
|---|
| 640 |
carry = bigintLLDecV(&r.d[y.d.length], &x.d[y.d.length], y.sign, carry, x.d.length-y.d.length); |
|---|
| 641 |
} |
|---|
| 642 |
r.d[r.d.length-1] = x.d[x.d.length-1] - y.d[y.d.length-1] - carry; |
|---|
| 643 |
minimize(r); |
|---|
| 644 |
return neg ? -r : r; |
|---|
| 645 |
} |
|---|
| 646 |
|
|---|
| 647 |
Int opSub(int y) |
|---|
| 648 |
{ |
|---|
| 649 |
if (y == 0) return this; |
|---|
| 650 |
|
|---|
| 651 |
Int x = this; |
|---|
| 652 |
Int r = new Int; |
|---|
| 653 |
r.d.length = x.d.length + 1; |
|---|
| 654 |
|
|---|
| 655 |
ulong t = x.d[0] - cast(ulong) cast(uint) y; |
|---|
| 656 |
r.d[0] = t; |
|---|
| 657 |
uint carry = t > 0xFFFFFFFF; |
|---|
| 658 |
|
|---|
| 659 |
carry = bigintLLDecV(&r.d[1], &x.d[1], cast(uint) (y<0?-1:0), carry, x.d.length-1); |
|---|
| 660 |
r.d[x.d.length] = x.d[x.d.length-1] - (y<0?-1:0) - carry; |
|---|
| 661 |
return minimize(r); |
|---|
| 662 |
} |
|---|
| 663 |
|
|---|
| 664 |
Int opSub(uint y) |
|---|
| 665 |
{ |
|---|
| 666 |
if (y == 0) return this; |
|---|
| 667 |
uint carry; |
|---|
| 668 |
|
|---|
| 669 |
Int x = this; |
|---|
| 670 |
Int r = new Int; |
|---|
| 671 |
r.d.length = x.d.length + 1; |
|---|
| 672 |
|
|---|
| 673 |
carry = bigintLLDec(r.d, x.d, y, x.d.length); |
|---|
| 674 |
r.d[x.d.length] = x.d[x.d.length-1] - carry; |
|---|
| 675 |
return minimize(r); |
|---|
| 676 |
} |
|---|
| 677 |
|
|---|
| 678 |
Int opSub_r(uint n) |
|---|
| 679 |
{ |
|---|
| 680 |
return new Int(n) - this; |
|---|
| 681 |
} |
|---|
| 682 |
|
|---|
| 683 |
Int opSub_r(int n) |
|---|
| 684 |
{ |
|---|
| 685 |
return new Int(n) - this; |
|---|
| 686 |
} |
|---|
| 687 |
|
|---|
| 688 |
// -------- Negation -------- |
|---|
| 689 |
|
|---|
| 690 |
Int opNeg() |
|---|
| 691 |
{ |
|---|
| 692 |
if (equalsZero) return this; |
|---|
| 693 |
Int r = new Int; |
|---|
| 694 |
r.d.length = d.length + 1; |
|---|
| 695 |
uint carry = bigintLLNeg(r.d, d, d.length); |
|---|
| 696 |
r.d[r.d.length-1] = 0 - d[d.length-1] - carry; |
|---|
| 697 |
return minimize(r); |
|---|
| 698 |
} |
|---|
| 699 |
|
|---|
| 700 |
// -------- Multiplication -------- |
|---|
| 701 |
|
|---|
| 702 |
Int opMul(Int y) |
|---|
| 703 |
{ |
|---|
| 704 |
Int x = this; |
|---|
| 705 |
if (x.sign) |
|---|
| 706 |
{ |
|---|
| 707 |
if (y.sign) return -x * -y; |
|---|
| 708 |
else return -(-x * y); |
|---|
| 709 |
} |
|---|
| 710 |
if (y.sign) |
|---|
| 711 |
{ |
|---|
| 712 |
return -(x * -y); |
|---|
| 713 |
} |
|---|
| 714 |
if (x.d.length < y.d.length) |
|---|
| 715 |
{ |
|---|
| 716 |
x = y; |
|---|
| 717 |
y = this; |
|---|
| 718 |
} |
|---|
| 719 |
if (y.isUint()) |
|---|
| 720 |
{ |
|---|
| 721 |
return x * y.d[0]; |
|---|
| 722 |
} |
|---|
| 723 |
|
|---|
| 724 |
Int r = new Int; |
|---|
| 725 |
r.d.length = x.d.length + y.d.length - 1; |
|---|
| 726 |
|
|---|
| 727 |
bigintMul(r.d, r.d.length-1, x.d, x.d.length-1, y.d, y.d.length-1); |
|---|
| 728 |
return minimize(r); |
|---|
| 729 |
} |
|---|
| 730 |
|
|---|
| 731 |
Int opMul(int y) |
|---|
| 732 |
{ |
|---|
| 733 |
return (y < 0) ? -opMul(cast(uint)-y) : opMul(cast(uint)y); |
|---|
| 734 |
} |
|---|
| 735 |
|
|---|
| 736 |
Int opMul(uint y) |
|---|
| 737 |
{ |
|---|
| 738 |
switch (y) |
|---|
| 739 |
{ |
|---|
| 740 |
case 0: return ZERO; |
|---|
| 741 |
case 1: return this; |
|---|
| 742 |
case 2: return this + this; |
|---|
| 743 |
case 3: return this + this + this; |
|---|
| 744 |
case 4: return this << 2u; |
|---|
| 745 |
case 5: return (this << 2u) + this; |
|---|
| 746 |
case 6: return (this << 2u) + this + this; |
|---|
| 747 |
case 7: return (this << 3u) - this; |
|---|
| 748 |
case 8: return this << 3u; |
|---|
| 749 |
case 9: return (this << 3u) + this; |
|---|
| 750 |
case 10: return (this << 3u) + this + this; |
|---|
| 751 |
default: break; |
|---|
| 752 |
} |
|---|
| 753 |
Int r = new Int; |
|---|
| 754 |
r.d.length = d.length + 1; |
|---|
| 755 |
|
|---|
| 756 |
r.d[d.length-1] = bigintLLMul(r.d, d, y, d.length-1); |
|---|
| 757 |
return minimize(r); |
|---|
| 758 |
} |
|---|
| 759 |
|
|---|
| 760 |
// -------- Division -------- |
|---|
| 761 |
|
|---|
| 762 |
Int opDiv(Int n) |
|---|
| 763 |
{ |
|---|
| 764 |
Int r; |
|---|
| 765 |
return divMod(this, n, r, Round.TOWARD_ZERO); |
|---|
| 766 |
} |
|---|
| 767 |
|
|---|
| 768 |
Int opDiv(int n) |
|---|
| 769 |
{ |
|---|
| 770 |
Int r; |
|---|
| 771 |
return divMod(this, new Int(n), r, Round.TOWARD_ZERO); |
|---|
| 772 |
} |
|---|
| 773 |
|
|---|
| 774 |
Int opDiv(uint n) |
|---|
| 775 |
{ |
|---|
| 776 |
Int r; |
|---|
| 777 |
return divMod(this, new Int(n), r, Round.TOWARD_ZERO); |
|---|
| 778 |
} |
|---|
| 779 |
|
|---|
| 780 |
Int opDiv_r(int n) |
|---|
| 781 |
{ |
|---|
| 782 |
return new Int(n) / this; |
|---|
| 783 |
} |
|---|
| 784 |
|
|---|
| 785 |
Int opDiv_r(uint n) |
|---|
| 786 |
{ |
|---|
| 787 |
return new Int(n) / this; |
|---|
| 788 |
} |
|---|
| 789 |
|
|---|
| 790 |
// -------- Remainder from division -------- |
|---|
| 791 |
|
|---|
| 792 |
Int opMod(Int n) |
|---|
| 793 |
{ |
|---|
| 794 |
Int r; |
|---|
| 795 |
divMod(this, n, r, Round.TOWARD_ZERO); |
|---|
| 796 |
return r; |
|---|
| 797 |
} |
|---|
| 798 |
|
|---|
| 799 |
Int opMod(int n) |
|---|
| 800 |
{ |
|---|
| 801 |
Int r; |
|---|
| 802 |
divMod(this, new Int(n), r, Round.TOWARD_ZERO); |
|---|
| 803 |
return r; |
|---|
| 804 |
} |
|---|
| 805 |
|
|---|
| 806 |
Int opMod(uint n) |
|---|
| 807 |
{ |
|---|
| 808 |
Int r; |
|---|
| 809 |
divMod(this, new Int(n), r, Round.TOWARD_ZERO); |
|---|
| 810 |
return r; |
|---|
| 811 |
} |
|---|
| 812 |
|
|---|
| 813 |
Int opMod_r(int n) |
|---|
| 814 |
{ |
|---|
| 815 |
return new Int(n) % this; |
|---|
| 816 |
} |
|---|
| 817 |
|
|---|
| 818 |
Int opMod_r(uint n) |
|---|
| 819 |
{ |
|---|
| 820 |
return new Int(n) % this; |
|---|
| 821 |
} |
|---|
| 822 |
|
|---|
| 823 |
// -------- Binary And -------- |
|---|
| 824 |
|
|---|
| 825 |
Int opAnd(Int y) |
|---|
| 826 |
{ |
|---|
| 827 |
Int r = new Int; |
|---|
| 828 |
Int x = this; |
|---|
| 829 |
int s = x.sign & y.sign; |
|---|
| 830 |
uint minlen = x.d.length - 1; |
|---|
| 831 |
uint maxlen = minlen; |
|---|
| 832 |
if (x.d.length > y.d.length) |
|---|
| 833 |
{ |
|---|
| 834 |
minlen = y.d.length - 1; |
|---|
| 835 |
if (y.sign) |
|---|
| 836 |
{ |
|---|
| 837 |
r.d.length = maxlen+1; |
|---|
| 838 |
r.d[minlen..maxlen] = x.d[minlen..maxlen]; |
|---|
| 839 |
} |
|---|
| 840 |
else |
|---|
| 841 |
{ |
|---|
| 842 |
r.d.length = minlen+1; |
|---|
| 843 |
} |
|---|
| 844 |
} |
|---|
| 845 |
else if (x.d.length < y.d.length) |
|---|
| 846 |
{ |
|---|
| 847 |
maxlen = y.d.length - 1; |
|---|
| 848 |
if (x.sign) |
|---|
| 849 |
{ |
|---|
| 850 |
r.d.length = maxlen+1; |
|---|
| 851 |
r.d[minlen..maxlen] = y.d[minlen..maxlen]; |
|---|
| 852 |
} |
|---|
| 853 |
else |
|---|
| 854 |
{ |
|---|
| 855 |
r.d.length = minlen+1; |
|---|
| 856 |
} |
|---|
| 857 |
} |
|---|
| 858 |
else |
|---|
| 859 |
{ |
|---|
| 860 |
r.d.length = minlen+1; |
|---|
| 861 |
} |
|---|
| 862 |
bigintLLAnd(r.d, x.d, y.d, minlen); |
|---|
| 863 |
r.d[r.d.length-1] = s; |
|---|
| 864 |
return minimize(r); |
|---|
| 865 |
} |
|---|
| 866 |
|
|---|
| 867 |
Int opAnd(int y) |
|---|
| 868 |
{ |
|---|
| 869 |
if (y < 0) |
|---|
| 870 |
{ |
|---|
| 871 |
uint n = d[0] & y; |
|---|
| 872 |
if (n == d[0]) return this; |
|---|
| 873 |
Int r = new Int(this); |
|---|
| 874 |
r.d[0] = n; |
|---|
| 875 |
return r; |
|---|
| 876 |
} |
|---|
| 877 |
else |
|---|
| 878 |
{ |
|---|
| 879 |
return new Int(y & d[0]); |
|---|
| 880 |
} |
|---|
| 881 |
} |
|---|
| 882 |
|
|---|
| 883 |
uint opAnd(uint y) |
|---|
| 884 |
{ |
|---|
| 885 |
return d[0] & y; |
|---|
| 886 |
} |
|---|
| 887 |
|
|---|
| 888 |
// -------- Binary Or -------- |
|---|
| 889 |
|
|---|
| 890 |
Int opOr(Int y) |
|---|
| 891 |
{ |
|---|
| 892 |
Int r = new Int; |
|---|
| 893 |
Int x = this; |
|---|
| 894 |
int s = x.sign | y.sign; |
|---|
| 895 |
uint minlen = x.d.length - 1; |
|---|
| 896 |
uint maxlen = minlen; |
|---|
| 897 |
if (x.d.length > y.d.length) |
|---|
| 898 |
{ |
|---|
| 899 |
minlen = y.d.length - 1; |
|---|
| 900 |
if (y.sign) |
|---|
| 901 |
{ |
|---|
| 902 |
r.d.length = minlen+1; |
|---|
| 903 |
} |
|---|
| 904 |
else |
|---|
| 905 |
{ |
|---|
| 906 |
r.d.length = maxlen+1; |
|---|
| 907 |
r.d[minlen..maxlen] = x.d[minlen..maxlen]; |
|---|
| 908 |
} |
|---|
| 909 |
} |
|---|
| 910 |
else if (x.d.length < y.d.length) |
|---|
| 911 |
{ |
|---|
| 912 |
maxlen = y.d.length - 1; |
|---|
| 913 |
if (x.sign) |
|---|
| 914 |
{ |
|---|
| 915 |
r.d.length = minlen+1; |
|---|
| 916 |
} |
|---|
| 917 |
else |
|---|
| 918 |
{ |
|---|
| 919 |
r.d.length = maxlen+1; |
|---|
| 920 |
r.d[minlen..maxlen] = y.d[minlen..maxlen]; |
|---|
| 921 |
} |
|---|
| 922 |
} |
|---|
| 923 |
else |
|---|
| 924 |
{ |
|---|
| 925 |
r.d.length = minlen+1; |
|---|
| 926 |
} |
|---|
| 927 |
bigintLLOr(r.d, x.d, y.d, minlen); |
|---|
| 928 |
r.d[r.d.length-1] = s; |
|---|
| 929 |
return minimize(r); |
|---|
| 930 |
} |
|---|
| 931 |
|
|---|
| 932 |
Int opOr(int y) |
|---|
| 933 |
{ |
|---|
| 934 |
if (y < 0) |
|---|
| 935 |
{ |
|---|
| 936 |
return new Int(cast(int) (y | d[0])); |
|---|
| 937 |
} |
|---|
| 938 |
else |
|---|
| 939 |
{ |
|---|
| 940 |
return this | (cast(uint) y); |
|---|
| 941 |
} |
|---|
| 942 |
} |
|---|
| 943 |
|
|---|
| 944 |
Int opOr(uint y) |
|---|
| 945 |
{ |
|---|
| 946 |
uint n = d[0] | y; |
|---|
| 947 |
if (n == d[0]) return this; |
|---|
| 948 |
Int r = new Int(this); |
|---|
| 949 |
r.d[0] = n; |
|---|
| 950 |
return r; |
|---|
| 951 |
} |
|---|
| 952 |
|
|---|
| 953 |
|
|---|
| 954 |
// -------- Binary Exclusive Or -------- |
|---|
| 955 |
|
|---|
| 956 |
Int opXor(Int y) |
|---|
| 957 |
{ |
|---|
| 958 |
Int r = new Int; |
|---|
| 959 |
Int x = this; |
|---|
| 960 |
int s = x.sign ^ y.sign; |
|---|
| 961 |
uint minlen = x.d.length - 1; |
|---|
| 962 |
uint maxlen = minlen; |
|---|
| 963 |
if (x.d.length > y.d.length) |
|---|
| 964 |
{ |
|---|
| 965 |
minlen = y.d.length - 1; |
|---|
| 966 |
r.d.length = maxlen + 1; |
|---|
| 967 |
|
|---|
| 968 |
if (y.sign) |
|---|
| 969 |
{ |
|---|
| 970 |
bigintLLCom(&r.d[minlen], &x.d[minlen], maxlen-minlen); |
|---|
| 971 |
} |
|---|
| 972 |
} |
|---|
| 973 |
else if (x.d.length < y.d.length) |
|---|
| 974 |
{ |
|---|
| 975 |
maxlen = y.d.length - 1; |
|---|
| 976 |
r.d.length = maxlen + 1; |
|---|
| 977 |
|
|---|
| 978 |
if (x.sign) |
|---|
| 979 |
{ |
|---|
| 980 |
bigintLLCom(&r.d[minlen], &y.d[minlen], maxlen-minlen); |
|---|
| 981 |
} |
|---|
| 982 |
} |
|---|
| 983 |
else |
|---|
| 984 |
{ |
|---|
| 985 |
r.d.length = minlen + 1; |
|---|
| 986 |
} |
|---|
| 987 |
bigintLLXor(r.d, x.d, y.d, minlen); |
|---|
| 988 |
r.d[maxlen] = s; |
|---|
| 989 |
return minimize(r); |
|---|
| 990 |
} |
|---|
| 991 |
|
|---|
| 992 |
Int opXor(int y) |
|---|
| 993 |
{ |
|---|
| 994 |
if (y < 0) |
|---|
| 995 |
{ |
|---|
| 996 |
Int r = new Int; |
|---|
| 997 |
r.d.length = d.length; |
|---|
| 998 |
|
|---|
| 999 |
r.d[0] = d[0] ^ y; |
|---|
| 1000 |
bigintLLCom(&r.d[1], &d[1], d.length-1); |
|---|
| 1001 |
return minimize(r); |
|---|
| 1002 |
} |
|---|
| 1003 |
else |
|---|
| 1004 |
{ |
|---|
| 1005 |
return this ^ (cast(uint) y); |
|---|
| 1006 |
} |
|---|
| 1007 |
} |
|---|
| 1008 |
|
|---|
| 1009 |
Int opXor(uint y) |
|---|
| 1010 |
{ |
|---|
| 1011 |
if (y == 0) return this; |
|---|
| 1012 |
Int r = new Int(this); |
|---|
| 1013 |
r.d[0] ^= y; |
|---|
| 1014 |
return r; |
|---|
| 1015 |
} |
|---|
| 1016 |
|
|---|
| 1017 |
// -------- Complement -------- |
|---|
| 1018 |
|
|---|
| 1019 |
Int opCom() |
|---|
| 1020 |
{ |
|---|
| 1021 |
Int r = new Int; |
|---|
| 1022 |
r.d.length = d.length; |
|---|
| 1023 |
bigintLLCom(r.d, d, d.length); |
|---|
| 1024 |
return r; |
|---|
| 1025 |
} |
|---|
| 1026 |
|
|---|
| 1027 |
// -------- Shift left -------- |
|---|
| 1028 |
|
|---|
| 1029 |
Int opShl(Int y) |
|---|
| 1030 |
{ |
|---|
| 1031 |
Int x = this; |
|---|
| 1032 |
if (y.isInt()) |
|---|
| 1033 |
{ |
|---|
| 1034 |
int k = y.d[0]; |
|---|
| 1035 |
return x << k; |
|---|
| 1036 |
} |
|---|
| 1037 |
if (y.sign) return x >> (-y); |
|---|
| 1038 |
if (x.equalsZero) return this; |
|---|
| 1039 |
throw new IntException("(x << y) overflow: y too big"); |
|---|
| 1040 |
} |
|---|
| 1041 |
|
|---|
| 1042 |
Int opShl(int y) |
|---|
| 1043 |
{ |
|---|
| 1044 |
if (y < 0) return this >> (cast(uint)-y); |
|---|
| 1045 |
return this << (cast(uint)y); |
|---|
| 1046 |
} |
|---|
| 1047 |
|
|---|
| 1048 |
Int opShl(uint y) |
|---|
| 1049 |
{ |
|---|
| 1050 |
if (y == 0) return this; |
|---|
| 1051 |
uint nDigits = y >> 5; |
|---|
| 1052 |
uint nBits = y & 0x1F; |
|---|
| 1053 |
|
|---|
| 1054 |
int neg = sign; |
|---|
| 1055 |
Int r = shlWhole(this, nDigits); |
|---|
| 1056 |
Int s = new Int; |
|---|
| 1057 |
s.d.length = r.d.length + 1; |
|---|
| 1058 |
bigintLLShl(&s.d[nDigits], &r.d[nDigits], nBits, r.d.length-nDigits); |
|---|
| 1059 |
s.d[s.d.length-1] = neg; |
|---|
| 1060 |
return minimize(s); |
|---|
| 1061 |
} |
|---|
| 1062 |
|
|---|
| 1063 |
Int opShl_r(int y) |
|---|
| 1064 |
{ |
|---|
| 1065 |
return (new Int(y)) << this; |
|---|
| 1066 |
} |
|---|
| 1067 |
|
|---|
| 1068 |
Int opShl_r(uint y) |
|---|
| 1069 |
{ |
|---|
| 1070 |
return (new Int(y)) << this; |
|---|
| 1071 |
} |
|---|
| 1072 |
|
|---|
| 1073 |
// -------- Shift right -------- |
|---|
| 1074 |
|
|---|
| 1075 |
Int opShr(Int y) |
|---|
| 1076 |
{ |
|---|
| 1077 |
if (y.isInt()) |
|---|
| 1078 |
{ |
|---|
| 1079 |
int k = y.d[0]; |
|---|
| 1080 |
return this >> k; |
|---|
| 1081 |
} |
|---|
| 1082 |
if (y.sign) return this << (-y); |
|---|
| 1083 |
return new Int(sign()); |
|---|
| 1084 |
} |
|---|
| 1085 |
|
|---|
| 1086 |
Int opShr(int y) |
|---|
| 1087 |
{ |
|---|
| 1088 |
if (y < 0) return this << (cast(uint)-y); |
|---|
| 1089 |
return this >> (cast(uint)y); |
|---|
| 1090 |
} |
|---|
| 1091 |
|
|---|
| 1092 |
Int opShr(uint y) |
|---|
| 1093 |
{ |
|---|
| 1094 |
if (y == 0) return this; |
|---|
| 1095 |
uint nDigits = y >> 5; |
|---|
| 1096 |
uint nBits = y & 0x1F; |
|---|
| 1097 |
|
|---|
| 1098 |
Int r = shrWhole(this, nDigits); |
|---|
| 1099 |
Int s = new Int; |
|---|
| 1100 |
s.d.length = r.d.length; |
|---|
| 1101 |
uint extraBits = (sign) ? (int.min >> nBits) << 1 : 0; |
|---|
| 1102 |
bigintLLShr(s.d, r.d, nBits, r.d.length); |
|---|
| 1103 |
s.d[s.d.length-1] |= extraBits; |
|---|
| 1104 |
return minimize(s); |
|---|
| 1105 |
} |
|---|
| 1106 |
|
|---|
| 1107 |
Int opShr_r(uint y) |
|---|
| 1108 |
{ |
|---|
| 1109 |
return (new Int(y)) >> this; |
|---|
| 1110 |
} |
|---|
| 1111 |
|
|---|
| 1112 |
Int opShr_r(int y) |
|---|
| 1113 |
{ |
|---|
| 1114 |
return (new Int(y)) >> this; |
|---|
| 1115 |
} |
|---|
| 1116 |
|
|---|
| 1117 |
// -------- Unsigned Shift right -------- |
|---|
| 1118 |
|
|---|
| 1119 |
Int opUShr(Int y) |
|---|
| 1120 |
{ |
|---|
| 1121 |
Int x = this; |
|---|
| 1122 |
if (y.isInt()) |
|---|
| 1123 |
{ |
|---|
| 1124 |
int k = y.d[0]; |
|---|
| 1125 |
return x >>> k; |
|---|
| 1126 |
} |
|---|
| 1127 |
if (y.sign) return x << (-y); |
|---|
| 1128 |
if (x.sign) throw new IntException("(x >>> y) not defined for x < 0"); |
|---|
| 1129 |
return ZERO; |
|---|
| 1130 |
} |
|---|
| 1131 |
|
|---|
| 1132 |
Int opUShr(int y) |
|---|
| 1133 |
{ |
|---|
| 1134 |
if (y < 0) return this << (cast(uint)-y); |
|---|
| 1135 |
return this >>> (cast(uint)y); |
|---|
| 1136 |
} |
|---|
| 1137 |
|
|---|
| 1138 |
Int opUShr(uint y) |
|---|
| 1139 |
{ |
|---|
| 1140 |
if (y == 0) return this; |
|---|
| 1141 |
if (sign) throw new IntException("(x >>> y) not defined for x < 0"); |
|---|
| 1142 |
return opShr(y); |
|---|
| 1143 |
} |
|---|
| 1144 |
|
|---|
| 1145 |
Int opUShr_r(uint y) |
|---|
| 1146 |
{ |
|---|
| 1147 |
return (new Int(y)) >>> this; |
|---|
| 1148 |
} |
|---|
| 1149 |
|
|---|
| 1150 |
Int opUShr_r(int y) |
|---|
| 1151 |
{ |
|---|
| 1152 |
return (new Int(y)) >>> this; |
|---|
| 1153 |
} |
|---|
| 1154 |
|
|---|
| 1155 |
// -------- Array dereferencing -------- |
|---|
| 1156 |
// |
|---|
| 1157 |
// These overloads are designed to give the illusion that an Int is actually an infinitely large array |
|---|
| 1158 |
|
|---|
| 1159 |
// uint length() purposefully not overloaded, because you can't actually HAVE an infinitely large array |
|---|
| 1160 |
// instead, we offer this: |
|---|
| 1161 |
|
|---|
| 1162 |
uint end() |
|---|
| 1163 |
{ |
|---|
| 1164 |
return d.length - 1; |
|---|
| 1165 |
} |
|---|
| 1166 |
|
|---|
| 1167 |
uint opIndex(int i) |
|---|
| 1168 |
{ |
|---|
| 1169 |
return (i < d.length) ? d[i] : d[d.length-1]; |
|---|
| 1170 |
} |
|---|
| 1171 |
|
|---|
| 1172 |
// uint opIndex(int i, int value) purposefully not overloaded because Ints are immutable |
|---|
| 1173 |
|
|---|
| 1174 |
// uint[] opSlice() purposefully not overloaded, because you can't actually HAVE an infinitely large array |
|---|
| 1175 |
|
|---|
| 1176 |
uint[] opSlice(int i, int j) |
|---|
| 1177 |
{ |
|---|
| 1178 |
uint[] t; |
|---|
| 1179 |
if (i >= j) return t; //empty array |
|---|
| 1180 |
t.length = j-i; |
|---|
| 1181 |
if (j <= d.length) |
|---|
| 1182 |
{ |
|---|
| 1183 |
t[] = d[i..j]; |
|---|
| 1184 |
} |
|---|
| 1185 |
else |
|---|
| 1186 |
{ |
|---|
| 1187 |
uint s = sign; |
|---|
| 1188 |
if (i >= d.length) |
|---|
| 1189 |
{ |
|---|
| 1190 |
t[] = s; |
|---|
| 1191 |
} |
|---|
| 1192 |
else |
|---|
| 1193 |
{ |
|---|
| 1194 |
t[0..d.length-i] = d[i..d.length]; |
|---|
| 1195 |
t[d.length-i..j-i] = s; |
|---|
| 1196 |
} |
|---|
| 1197 |
} |
|---|
| 1198 |
return t; |
|---|
| 1199 |
} |
|---|
| 1200 |
|
|---|
| 1201 |
/* |
|---|
| 1202 |
And so end the operator overloads. |
|---|
| 1203 |
|
|---|
| 1204 |
Now, one big problem with big integers is that printf() doesn't recognise them. |
|---|
| 1205 |
For this reason, we present a format function. |
|---|
| 1206 |
Its parameter is a fragment of a printf() format string, starting with "%" and ending with "d". |
|---|
| 1207 |
*/ |
|---|
| 1208 |
|
|---|
| 1209 |
enum SignMode { NORMAL, MINUS_SPACE, MINUS_SPACE_PLUS } |
|---|
| 1210 |
char[] format(uint radix, uint minWidth, uint groupWidth, bool leadingZeroes, SignMode signMode) |
|---|
| 1211 |
{ |
|---|
| 1212 |
// Get a positive version of this |
|---|
| 1213 |
int actualSign = opCmp(0); |
|---|
| 1214 |
Int t = (actualSign < 0) ? -this : this; |
|---|
| 1215 |
char padChar = leadingZeroes ? '0' : ' '; |
|---|
| 1216 |
char[] s = bigintToString(t.d, radix, groupWidth); |
|---|
| 1217 |
|
|---|
| 1218 |
// Now make somewhere for the final result |
|---|
| 1219 |
char[] u; |
|---|
| 1220 |
uint tLen = s.length + 1; |
|---|
| 1221 |
if (tLen < minWidth) tLen = minWidth; |
|---|
| 1222 |
u.length = tLen; |
|---|
| 1223 |
|
|---|
| 1224 |
// Copy in the string |
|---|
| 1225 |
uint padSpace = u.length - s.length; |
|---|
| 1226 |
u[0..padSpace] = padChar; |
|---|
| 1227 |
u[padSpace..u.length] = s[0..s.length]; |
|---|
| 1228 |
|
|---|
| 1229 |
// Write in the sign |
|---|
| 1230 |
uint signPos = (leadingZeroes) ? 0 : padSpace-1; |
|---|
| 1231 |
if (actualSign < 0) |
|---|
| 1232 |
{ |
|---|
| 1233 |
u[signPos] = '-'; |
|---|
| 1234 |
} |
|---|
| 1235 |
else if (signMode == SignMode.NORMAL) |
|---|
| 1236 |
{ |
|---|
| 1237 |
uint realLength = (s.length > minWidth) ? s.length : minWidth; |
|---|
| 1238 |
u = u[u.length-realLength..u.length]; |
|---|
| 1239 |
} |
|---|
| 1240 |
else if (actualSign == 0 || signMode == SignMode.MINUS_SPACE) |
|---|
| 1241 |
{ |
|---|
| 1242 |
u[signPos] = ' '; |
|---|
| 1243 |
} |
|---|
| 1244 |
else |
|---|
| 1245 |
{ |
|---|
| 1246 |
u[signPos] = '+'; |
|---|
| 1247 |
} |
|---|
| 1248 |
s[] = 0; |
|---|
| 1249 |
return u; |
|---|
| 1250 |
} |
|---|
| 1251 |
|
|---|
| 1252 |
/* |
|---|
| 1253 |
The functions below are intended to be fast and simple. |
|---|
| 1254 |
*/ |
|---|
| 1255 |
|
|---|
| 1256 |
/* returns true if this is zero; false if this is non-zero */ |
|---|
| 1257 |
bool equalsZero() |
|---|
| 1258 |
{ |
|---|
| 1259 |
return ((d[0]==0) && (d[1]==0) && (d.length == 2)); |
|---|
| 1260 |
} |
|---|
| 1261 |
|
|---|
| 1262 |
/* returns true if this is positive; false if this is negative or zero */ |
|---|
| 1263 |
bool positive() |
|---|
| 1264 |
{ |
|---|
| 1265 |
if (sign) return false; |
|---|
| 1266 |
return (!equalsZero()); |
|---|
| 1267 |
} |
|---|
| 1268 |
|
|---|
| 1269 |
/* returns true if this is negative; false if this is positive or zero */ |
|---|
| 1270 |
bool negative() |
|---|
| 1271 |
{ |
|---|
| 1272 |
return (sign < 0); |
|---|
| 1273 |
} |
|---|
| 1274 |
|
|---|
| 1275 |
/* returns -1 if this is sign; 0 if this is positive or zero */ |
|---|
| 1276 |
int sign() |
|---|
| 1277 |
{ |
|---|
| 1278 |
return d[d.length-1]; |
|---|
| 1279 |
} |
|---|
| 1280 |
|
|---|
| 1281 |
// Change the sign field of a number without negating it. That is, change the interpretation of its bit pattern |
|---|
| 1282 |
Int changeSign() |
|---|
| 1283 |
{ |
|---|
| 1284 |
Int r = new Int(this); |
|---|
| 1285 |
r.d[r.d.length-1] = ~r.d[r.d.length-1]; |
|---|
| 1286 |
return r; |
|---|
| 1287 |
} |
|---|
| 1288 |
} |
|---|
| 1289 |
|
|---|
| 1290 |
package |
|---|
| 1291 |
{ |
|---|
| 1292 |
this() |
|---|
| 1293 |
{ |
|---|
| 1294 |
} |
|---|
| 1295 |
|
|---|
| 1296 |
this(uint[] t) |
|---|
| 1297 |
{ |
|---|
| 1298 |
d = t; |
|---|
| 1299 |
minimize(this); |
|---|
| 1300 |
} |
|---|
| 1301 |
|
|---|
| 1302 |
this(Int n) |
|---|
| 1303 |
{ |
|---|
| 1304 |
d.length = n.d.length; |
|---|
| 1305 |
d[] = n.d[]; |
|---|
| 1306 |
} |
|---|
| 1307 |
|
|---|
| 1308 |
//----------------------------------- |
|---|
| 1309 |
// The member variables of this class |
|---|
| 1310 |
|
|---|
| 1311 |
uint[] d; |
|---|
| 1312 |
|
|---|
| 1313 |
//================================================== |
|---|
| 1314 |
|
|---|
| 1315 |
// A generalization of this to the power of e. |
|---|
| 1316 |
Int powGen(Int e, Int r, FMul f) |
|---|
| 1317 |
in |
|---|
| 1318 |
{ |
|---|
| 1319 |
assert(e >= 0); |
|---|
| 1320 |
} |
|---|
| 1321 |
body |
|---|
| 1322 |
{ |
|---|
| 1323 |
Int x = this; |
|---|
| 1324 |
if (x.equalsZero) return x; |
|---|
| 1325 |
if (e.equalsZero) return r; |
|---|
| 1326 |
|
|---|
| 1327 |
// We unroll what would otherwise have been the first pass of the i-loop, for speed. |
|---|
| 1328 |
// Note that i starts off at e.length-2, because: |
|---|
| 1329 |
// e.d[e.length-1] = the sign word, guaranteed to equal 0x00000000 in this case. |
|---|
| 1330 |
// e.d[e.length-2] = the most significant d of e. |
|---|
| 1331 |
|
|---|
| 1332 |
int i = e.d.length - 2; |
|---|
| 1333 |
for (int j=bsr(e.d[i]); j>=0; --j) |
|---|
| 1334 |
{ |
|---|
| 1335 |
r = f(r,r); |
|---|
| 1336 |
if (bt(&e.d[i],j)) |
|---|
| 1337 |
{ |
|---|
| 1338 |
r = f(r,x); |
|---|
| 1339 |
} |
|---|
| 1340 |
} |
|---|
| 1341 |
|
|---|
| 1342 |
// Below is the rest of the i-loop. From now on, j has to test every single bit. |
|---|
| 1343 |
// Note that i starts off at e.length-3, because the first pass of the loop was |
|---|
| 1344 |
// unrolled, and carried out above. |
|---|
| 1345 |
|
|---|
| 1346 |
for (i=e.d.length-3; i>=0; --i) |
|---|
| 1347 |
{ |
|---|
| 1348 |
for (int j=31; j>=0; --j) |
|---|
| 1349 |
{ |
|---|
| 1350 |
r = f(r, r); |
|---|
| 1351 |
if (bt(&e.d[i],j)) |
|---|
| 1352 |
{ |
|---|
| 1353 |
r = f(r, x); |
|---|
| 1354 |
} |
|---|
| 1355 |
} |
|---|
| 1356 |
} |
|---|
| 1357 |
return r; |
|---|
| 1358 |
} |
|---|
| 1359 |
} |
|---|
| 1360 |
} |
|---|
| 1361 |
|
|---|
| 1362 |
// Private helper functions follow |
|---|
| 1363 |
|
|---|
| 1364 |
private |
|---|
| 1365 |
{ |
|---|
| 1366 |
Int minimize(Int x) |
|---|
| 1367 |
{ |
|---|
| 1368 |
uint len = bigintLLMinimizeV(x.d, x.d[x.d.length-1], x.d.length); |
|---|
| 1369 |
if (len <= 1) |
|---|
| 1370 |
{ |
|---|
| 1371 |
x.d.length = 2; |
|---|
| 1372 |
} |
|---|
| 1373 |
else |
|---|
| 1374 |
{ |
|---|
| 1375 |
x.d.length = len + 1; |
|---|
| 1376 |
} |
|---|
| 1377 |
return x; |
|---|
| 1378 |
} |
|---|
| 1379 |
} |
|---|
| 1380 |
|
|---|
| 1381 |
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 1382 |
Public helper functions follow |
|---|
| 1383 |
*/ |
|---|
| 1384 |
|
|---|
| 1385 |
// get the absolute value of a number |
|---|
| 1386 |
Int abs(Int x) |
|---|
| 1387 |
{ |
|---|
| 1388 |
return (x.sign) ? -x : x; |
|---|
| 1389 |
} |
|---|
| 1390 |
|
|---|
| 1391 |
// Returns -1, 0 or +1 according to the sign of x |
|---|
| 1392 |
int sgn(Int x) |
|---|
| 1393 |
{ |
|---|
| 1394 |
if (x.sign) return -1; |
|---|
| 1395 |
return (x.equalsZero) ? 0 : 1; |
|---|
| 1396 |
} |
|---|
| 1397 |
|
|---|
| 1398 |
// test a bit |
|---|
| 1399 |
bit bitTest(Int x, uint n) |
|---|
| 1400 |
{ |
|---|
| 1401 |
uint nDigits = n >>> 5; |
|---|
| 1402 |
uint nBits = n & 0x1F; |
|---|
| 1403 |
if (nDigits >= x.d.length) return (x.sign == 0) ? 0 : 1; |
|---|
| 1404 |
return (bts(&x.d[nDigits], nBits) == 0) ? 0 : 1; |
|---|
| 1405 |
} |
|---|
| 1406 |
|
|---|
| 1407 |
// set a bit. (More precisely, return a copy of x, with the appropriate bit set). |
|---|
| 1408 |
Int bitSet(Int x, int n) |
|---|
| 1409 |
{ |
|---|
| 1410 |
return x | pow2(n); |
|---|
| 1411 |
} |
|---|
| 1412 |
|
|---|
| 1413 |
// reset a bit. (More precisely, return a copy of x, with the appropriate bit set). |
|---|
| 1414 |
Int bitClear(Int x, int n) |
|---|
| 1415 |
{ |
|---|
| 1416 |
return x & ~pow2(n); |
|---|
| 1417 |
} |
|---|
| 1418 |
|
|---|
| 1419 |
// get the number of trailing zero bits in this (ge2 means Greatest Power of 2) |
|---|
| 1420 |
uint ge2(Int x) |
|---|
| 1421 |
{ |
|---|
| 1422 |
for (uint i=0; i<x.d.length; ++i) |
|---|
| 1423 |
{ |
|---|
| 1424 |
int n = bsf(x.d[i]); |
|---|
| 1425 |
if (n >= 0) return n; |
|---|
| 1426 |
} |
|---|
| 1427 |
throw new IntException("ge2(x) not defined for x == 0"); |
|---|
| 1428 |
} |
|---|
| 1429 |
|
|---|
| 1430 |
uint ge2(int x) |
|---|
| 1431 |
{ |
|---|
| 1432 |
return ge2(cast(uint) x); |
|---|
| 1433 |
} |
|---|
| 1434 |
|
|---|
| 1435 |
uint ge2(uint x) |
|---|
| 1436 |
{ |
|---|
| 1437 |
int n = bsf(x); |
|---|
| 1438 |
if (n >= 0) return n; |
|---|
| 1439 |
throw new IntException("ge2(x) not defined for x == 0"); |
|---|
| 1440 |
} |
|---|
| 1441 |
|
|---|
| 1442 |
|
|---|
| 1443 |
// get the number of bits in this (less one) |
|---|
| 1444 |
uint log2(Int x) |
|---|
| 1445 |
{ |
|---|
| 1446 |
if (!x.positive) throw new IntException("log2(x) not defined for x <= 0"); |
|---|
| 1447 |
return bsr(x.d[x.d.length-2]) + ((x.d.length-2)<<5); |
|---|
| 1448 |
} |
|---|
| 1449 |
|
|---|
| 1450 |
uint log2(int x) |
|---|
| 1451 |
{ |
|---|
| 1452 |
if (x <= 0) throw new IntException("log2(x) not defined for x <= 0"); |
|---|
| 1453 |
return bsr(x); |
|---|
| 1454 |
} |
|---|
| 1455 |
|
|---|
| 1456 |
uint log2(uint x) |
|---|
| 1457 |
{ |
|---|
| 1458 |
if (x == 0) throw new IntException("log2(x) not defined for x == 0"); |
|---|
| 1459 |
return bsr(x); |
|---|
| 1460 |
} |
|---|
| 1461 |
|
|---|
| 1462 |
// returns two to a given power |
|---|
| 1463 |
Int pow2(int x) |
|---|
| 1464 |
{ |
|---|
| 1465 |
if (x < 0) throw new IntException("pow2(x) not defined for x < 0"); |
|---|
| 1466 |
uint nDigits = x >>> 5; |
|---|
| 1467 |
uint nBits = x & 0x1F; |
|---|
| 1468 |
Int r = new Int(); |
|---|
| 1469 |
r.d.length = nDigits + 2; |
|---|
| 1470 |
r.d[nDigits] = 1 << nBits; |
|---|
| 1471 |
return r; |
|---|
| 1472 |
} |
|---|
| 1473 |
|
|---|
| 1474 |
// test whether or not a bigint is an exact power of two |
|---|
| 1475 |
bool isPow2(Int x) |
|---|
| 1476 |
{ |
|---|
| 1477 |
if (!x.positive) return false; |
|---|
| 1478 |
if (isPow2(x.d[x.d.length-2])) |
|---|
| 1479 |
{ |
|---|
| 1480 |
return bigintLLEqualsZero(x.d, x.d.length-2); |
|---|
| 1481 |
} |
|---|
| 1482 |
return false; |
|---|
| 1483 |
} |
|---|
| 1484 |
|
|---|
| 1485 |
bool isPow2(int x) |
|---|
| 1486 |
{ |
|---|
| 1487 |
if (x <= 0) return false; |
|---|
| 1488 |
return isPow2(cast(uint) x); |
|---|
| 1489 |
} |
|---|
| 1490 |
|
|---|
| 1491 |
bool isPow2(uint x) |
|---|
| 1492 |
{ |
|---|
| 1493 |
return (log2Exact(x) >= 0); |
|---|
| 1494 |
} |
|---|
| 1495 |
|
|---|
| 1496 |
// Count the number of one bits in a uint |
|---|
| 1497 |
uint countOnes(Int x) |
|---|
| 1498 |
{ |
|---|
| 1499 |
if (x.sign) throw new IntException("countOnes(x) not defined for x < 0"); |
|---|
| 1500 |
return bigintLLCountOnes(x.d, x.d.length-1); |
|---|
| 1501 |
} |
|---|
| 1502 |
|
|---|
| 1503 |
uint countOnes(int x) |
|---|
| 1504 |
{ |
|---|
| 1505 |
if (x < 0) throw new IntException("countOnes(x) not defined for x < 0"); |
|---|
| 1506 |
return countOnes(cast(uint) x); |
|---|
| 1507 |
} |
|---|
| 1508 |
|
|---|
| 1509 |
uint countOnes(uint x) |
|---|
| 1510 |
{ |
|---|
| 1511 |
return bigintLLCountOnes(&x, 1); |
|---|
| 1512 |
} |
|---|
| 1513 |
|
|---|
| 1514 |
// Shift one number left by a whole number of uints. That is, perform x << (32*y). |
|---|
| 1515 |
Int shlWhole(Int x, uint y) |
|---|
| 1516 |
{ |
|---|
| 1517 |
if (y == 0) return x; |
|---|
| 1518 |
Int r = new Int; |
|---|
| 1519 |
r.d.length = x.d.length + y; |
|---|
| 1520 |
r.d[y..r.d.length] = x[0..x.d.length]; |
|---|
| 1521 |
return r; |
|---|
| 1522 |
} |
|---|
| 1523 |
|
|---|
| 1524 |
Int shlWhole(int x, uint y) |
|---|
| 1525 |
{ |
|---|
| 1526 |
Int r = new Int; |
|---|
| 1527 |
r.d.length = y + 2; |
|---|
| 1528 |
r.d[y] = x; |
|---|
| 1529 |
r.d[y+1] = x<0 ? -1U : 0; |
|---|
| 1530 |
return r; |
|---|
| 1531 |
} |
|---|
| 1532 |
|
|---|
| 1533 |
Int shrWhole(Int x, uint y) |
|---|
| 1534 |
{ |
|---|
| 1535 |
if (y == 0) return x; |
|---|
| 1536 |
Int r = new Int; |
|---|
| 1537 |
if (x.d.length > y+2) |
|---|
| 1538 |
{ |
|---|
| 1539 |
r.d.length = x.d.length - y; |
|---|
| 1540 |
r.d[] = x.d[y..x.d.length]; |
|---|
| 1541 |
} |
|---|
| 1542 |
else |
|---|
| 1543 |
{ |
|---|
| 1544 |
r.d.length = 2; |
|---|
| 1545 |
r.d[] = x.d[x.d.length-2..x.d.length]; |
|---|
| 1546 |
} |
|---|
| 1547 |
return r; |
|---|
| 1548 |
} |
|---|
| 1549 |
|
|---|
| 1550 |
// Return the low part of a number. That is, x & (1<<(32*y))-1 |
|---|
| 1551 |
Int lowWhole(Int x, uint y) |
|---|
| 1552 |
{ |
|---|
| 1553 |
if (y == x.end) return x; |
|---|
| 1554 |
Int r = new Int; |
|---|
| 1555 |
r.d.length = y + 1; |
|---|
| 1556 |
r.d[0..y] = x[0..y]; |
|---|
| 1557 |
return minimize(r); |
|---|
| 1558 |
} |
|---|
| 1559 |
|
|---|
| 1560 |
// Return x / y and assign d = x % y |
|---|
| 1561 |
Int divMod(Int x, Int y, out Int r) |
|---|
| 1562 |
{ |
|---|
| 1563 |
return divMod(x, y, r, Int.Round.TOWARD_ZERO); |
|---|
| 1564 |
} |
|---|
| 1565 |
|
|---|
| 1566 |
Int divMod(Int x, Int y, out Int r, Int.Round mode) |
|---|
| 1567 |
out(q) |
|---|
| 1568 |
{ |
|---|
| 1569 |
assert(y*q+r == x); |
|---|
| 1570 |
} |
|---|
| 1571 |
body |
|---|
| 1572 |
{ |
|---|
| 1573 |
if (y.equalsZero()) throw new IntException("Divide by zero"); |
|---|
| 1574 |
|
|---|
| 1575 |
int xSign = x.sign; |
|---|
| 1576 |
int ySign = y.sign; |
|---|
| 1577 |
Int xa = (xSign < 0) ? -x : x; |
|---|
| 1578 |
Int ya = (ySign < 0) ? -y : y; |
|---|
| 1579 |
|
|---|
| 1580 |
Int q; |
|---|
| 1581 |
if (xa < ya) |
|---|
| 1582 |
{ |
|---|
| 1583 |
q = Int.ZERO; |
|---|
| 1584 |
r = xa; |
|---|
| 1585 |
} |
|---|
| 1586 |
else |
|---|
| 1587 |
{ |
|---|
| 1588 |
q = new Int; |
|---|
| 1589 |
q.d.length = xa.d.length - ya.d.length + 2; |
|---|
| 1590 |
r = new Int; |
|---|
| 1591 |
r.d.length = ya.d.length; |
|---|
| 1592 |
bigintDivMod(q.d, q.d.length-1, r.d, r.d.length-1, xa.d, xa.d.length-1, ya.d, ya.d.length-1); |
|---|
| 1593 |
minimize(q); |
|---|
| 1594 |
minimize(r); |
|---|
| 1595 |
} |
|---|
| 1596 |
|
|---|
| 1597 |
if (xSign != ySign) q = -q; |
|---|
| 1598 |
if (xSign < 0) r = -r; |
|---|
| 1599 |
|
|---|
| 1600 |
if (!r.equalsZero()) |
|---|
| 1601 |
{ |
|---|
| 1602 |
switch (mode) |
|---|
| 1603 |
{ |
|---|
| 1604 |
case Int.Round.TOWARD_ZERO: |
|---|
| 1605 |
break; |
|---|
| 1606 |
|
|---|
| 1607 |
case Int.Round.TOWARD_INFINITY: |
|---|
| 1608 |
if (xSign == ySign) |
|---|
| 1609 |
{ |
|---|
| 1610 |
q = q + 1; |
|---|
| 1611 |
r = r - y; |
|---|
| 1612 |
} |
|---|
| 1613 |
break; |
|---|
| 1614 |
|
|---|
| 1615 |
case Int.Round.TOWARD_MINUS_INFINITY: |
|---|
| 1616 |
if (xSign != ySign) |
|---|
| 1617 |
{ |
|---|
| 1618 |
q = q - 1; |
|---|
| 1619 |
r = r + y; |
|---|
| 1620 |
} |
|---|
| 1621 |
break; |
|---|
| 1622 |
} |
|---|
| 1623 |
} |
|---|
| 1624 |
return q; |
|---|
| 1625 |
} |
|---|
| 1626 |
|
|---|
| 1627 |
package class FMul |
|---|
| 1628 |
{ |
|---|
| 1629 |
abstract Int opCall(Int x, Int y); |
|---|
| 1630 |
} |
|---|