2 /*--------------------------------------------------------------------------*\
3 Copyright (C) 1999 Douglas W. Sauder
5 This software is provided "as is," without any express or implied
6 warranty. In no event will the author be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 The original distribution can be obtained from www.hunnysoft.com.
22 You can email the author, Doug Sauder, at dwsauder@erols.com.
27 \*--------------------------------------------------------------------------*/
33 static void i64_udiv_impl(bigint dividend
, bigint divisor
, bigint
*quotient
,
44 int i64_cmp(bigint n1
, bigint n2
)
49 if ((int) n1
.hi
< (int) n2
.hi
) {
52 else if (n1
.hi
== n2
.hi
) {
56 else if (n1
.lo
== n2
.lo
) {
71 int i64_sgn(bigint n1
)
76 if (n1
.hi
& 0x80000000) {
79 else if ((n1
.hi
| n1
.lo
) == 0) {
87 * Left shift n by b bits. Undefined if b is negative.
89 bigint
i64_lshift(bigint n
, int b
)
94 n
.hi
+= n
.lo
>> (32 - b
);
98 n
.hi
= n
.lo
<< (b
- 32);
111 * Unsigned right shift n by b bits. Zeros are always shifted in.
112 * Undefined if b is negative.
114 bigint
i64_urshift(bigint n
, int b
)
119 n
.lo
+= n
.hi
<< (32 - b
);
123 n
.lo
= n
.hi
>> (b
- 32);
136 * Signed right shift n by b bits. Bit shifted in matches most significant
137 * bit in n. Undefined if b is negative.
139 bigint
i64_srshift(bigint n
, int b
)
145 if (n
.hi
& 0x80000000) {
150 n
.lo
+= n
.hi
<< (32 - b
);
152 n
.hi
+= m
<< (32 - b
);
157 n
.lo
+= m
<< (32 - b
);
170 * Change sign operation (additive inverse)
174 bigint
i64_inv(bigint n
)
178 r
.lo
= (unsigned) - (int) n
.lo
;
180 r
.hi
= (unsigned) - (int) n
.hi
;
182 else /* if (r.lo != 0) */ {
192 bigint
i64_add(bigint n1
, bigint n2
)
197 sum
.lo
= n1
.lo
+ n2
.lo
;
198 c
= (n1
.lo
& n2
.lo
) | ((~sum
.lo
) & (n1
.lo
| n2
.lo
));
200 sum
.hi
= n1
.hi
+ n2
.hi
+ c
;
206 * Subtract n2 from n1
208 bigint
i64_sub(bigint n1
, bigint n2
)
213 diff
.lo
= n1
.lo
- n2
.lo
;
214 c
= (diff
.lo
& n2
.lo
) | ((~n1
.lo
) & (diff
.lo
| n2
.lo
));
216 diff
.hi
= n1
.hi
- n2
.hi
- c
;
224 bigint
i64_mul(bigint n1
, bigint n2
)
228 unsigned m1_0
, m1_1
, m1_2
, m1_3
;
229 unsigned m2_0
, m2_1
, m2_2
, m2_3
;
233 if (n1
.hi
& 0x80000000) {
235 prodIsMinus
= ~prodIsMinus
;
237 if (n2
.hi
& 0x80000000) {
239 prodIsMinus
= ~prodIsMinus
;
243 m1_2
= n1
.hi
& 0xffff;
245 m1_0
= n1
.lo
& 0xffff;
248 m2_2
= n2
.hi
& 0xffff;
250 m2_0
= n2
.lo
& 0xffff;
253 prod
.lo
= ms
& 0xffff;
264 prod
.hi
+= (m1_0
* m2_2
) + (m1_1
* m2_1
) + (m1_2
* m2_0
);
266 ms
= (m1_0
* m2_3
) + (m1_1
* m2_2
) + (m1_2
* m2_1
) + (m1_3
* m2_0
);
270 prod
= i64_inv(prod
);
277 static char leftZerosInByte
[] = {
278 /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */
279 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
280 /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f */
281 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
282 /* 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f */
283 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
284 /* 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f */
285 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
286 /* 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f */
287 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
288 /* 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f */
289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
290 /* 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f */
291 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
292 /* 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f */
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
294 /* 80 81 82 83 84 78 86 87 88 89 8a 8b 8c 8d 8e 8f */
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
296 /* 90 91 92 93 94 98 96 97 98 99 9a 9b 9c 9d 9e 9f */
297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298 /* a0 a1 a2 a3 a4 a8 a6 a7 a8 a9 aa ab ac ad ae af */
299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300 /* b0 b1 b2 b3 b4 b8 b6 b7 b8 b9 ba bb bc bd be bf */
301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
302 /* c0 c1 c2 c3 c4 c8 c6 c7 c8 c9 ca cb cc cd ce cf */
303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
304 /* d0 d1 d2 d3 d4 d8 d6 d7 d8 d9 da db dc dd de df */
305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
306 /* e0 e1 e2 e3 e4 e8 e6 e7 e8 e9 ea eb ec ed ee ef */
307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
308 /* f0 f1 f2 f3 f4 f8 f6 f7 f8 f9 fa fb fc fd fe ff */
309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
316 void i64_div(bigint dividend
, bigint divisor
, bigint
*quotient
, bigint
*remainder
)
318 int quotientIsMinus
, remainderIsMinus
;
320 if ((divisor
.hi
| divisor
.lo
) == 0) {
323 if ((dividend
.hi
| dividend
.lo
) == 0) {
331 remainderIsMinus
= dividend
.hi
& 0x80000000;
332 if (remainderIsMinus
) {
333 dividend
= i64_inv(dividend
);
334 quotientIsMinus
= ~quotientIsMinus
;
336 if (divisor
.hi
& 0x80000000) {
337 divisor
= i64_inv(divisor
);
338 quotientIsMinus
= ~quotientIsMinus
;
340 i64_udiv_impl(dividend
, divisor
, quotient
, remainder
);
341 if (quotientIsMinus
) {
342 *quotient
= i64_inv(*quotient
);
344 if (remainderIsMinus
) {
345 *remainder
= i64_inv(*remainder
);
353 void i64_udiv(bigint dividend
, bigint divisor
, bigint
*quotient
, bigint
*remainder
)
355 if ((divisor
.hi
| divisor
.lo
) == 0) {
358 if ((dividend
.hi
| dividend
.lo
) == 0) {
365 i64_udiv_impl(dividend
, divisor
, quotient
, remainder
);
370 * Unsigned division implementation.
372 * Note: does not check argument values
374 static void i64_udiv_impl(bigint dividend
, bigint divisor
, bigint
*quotient
,
377 int i
, j
, m
, n
, d
, divisorLeftZeros
, dividendLeftZeros
;
378 unsigned v
[4], u
[5], q
[4], qh
, rh
, a
, b
, c
;
381 divisorLeftZeros
= 0;
385 divisorLeftZeros
+= leftZerosInByte
[n
];
387 mm
.hi
+= mm
.lo
>> 24;
391 divisorLeftZeros
+= leftZerosInByte
[n
];
393 dividendLeftZeros
= 0;
397 dividendLeftZeros
+= leftZerosInByte
[n
];
399 mm
.hi
+= mm
.lo
>> 24;
403 dividendLeftZeros
+= leftZerosInByte
[n
];
405 n
= (79 - divisorLeftZeros
) / 16;
406 m
= (79 - dividendLeftZeros
) / 16 - n
;
409 quotient
->hi
= dividend
.hi
/ divisor
.lo
;
410 rh
= dividend
.hi
% divisor
.lo
;
411 a
= (rh
<< 16) + (dividend
.lo
>> 16);
412 quotient
->lo
= (a
/ divisor
.lo
) << 16;
414 a
= (rh
<< 16) + (dividend
.lo
& 0xffff);
415 quotient
->lo
+= a
/ divisor
.lo
;
417 remainder
->lo
= a
% divisor
.lo
;
419 else /* if (n > 1) */ {
420 d
= divisorLeftZeros
& 0x0f;
423 u
[i
++] = (dividend
.lo
<< d
) & 0xffff;
424 u
[i
++] = dividend
.lo
>> (16 - d
) & 0xffff;
425 u
[i
++] = ((dividend
.hi
<< d
) +
426 ((dividend
.lo
>> 16) >> (16 - d
))) & 0xffff;
427 u
[i
++] = (dividend
.hi
>> (16 - d
)) & 0xffff;
428 u
[i
] = (dividend
.hi
>> 16) >> (16 - d
);
431 v
[i
++] = (divisor
.lo
<< d
) & 0xffff;
432 v
[i
++] = (divisor
.lo
>> (16 - d
)) & 0xffff;
433 v
[i
++] = ((divisor
.hi
<< d
) +
434 ((divisor
.lo
>> 16) >> (16 - d
))) & 0xffff;
435 v
[i
] = divisor
.hi
>> (16 - d
);
437 memset(q
, 0, sizeof(q
));
439 for (j
=m
; j
>= 0; --j
) {
440 a
= (u
[j
+n
] << 16) + u
[j
+n
-1];
443 if ((qh
& 0x30000) || qh
*v
[n
-2] > (rh
<< 16) + u
[j
+n
-2]) {
446 if (! (rh
& 0x10000)) {
447 if ((qh
& 0x30000) || qh
*v
[n
-2] > (rh
<< 16) + u
[j
+n
-2]) {
454 for (i
=0; i
< n
; ++i
) {
456 c
= u
[j
+i
] + c
+ ((~b
) & 0xffff);
461 c
= u
[j
+i
] + c
+ ((~b
) & 0xffff);
465 for (i
=0; i
< n
; ++i
) {
466 c
= u
[j
+i
] + v
[i
] + c
;
476 quotient
->hi
= (q
[3] << 16) + q
[2];
477 quotient
->lo
= (q
[1] << 16) + q
[0];
478 remainder
->hi
= (u
[3] << (16 - d
)) + (u
[2] >> d
);
479 remainder
->lo
= ((u
[2] << 16) << (16 - d
)) + (u
[1] << (16 - d
))
486 * Convert string to integer
488 bigint
i64_atoi(const char *str
)
491 bigint ten
, digit
, n
;
501 while (isspace(str
[i
])) {
508 else if (str
[i
] == '+') {
511 while (isdigit(str
[i
])) {
512 digit
.lo
= str
[i
] - '0';
514 n
= i64_add(digit
, n
);
525 * Convert integer to string
527 void i64_itoa(bigint n
, char *str
, int strSize
)
537 /* positive number */
538 if (i64_sgn(n
) > 0) {
539 while (n
.hi
!= 0 || n
.lo
!= 0) {
540 i64_div(n
, ten
, &n
, &digit
);
542 s
[pos
] = digit
.lo
+ '0';
545 /* negative number */
546 else if (i64_sgn(n
) < 0) {
548 while (n
.hi
!= 0 || n
.lo
!= 0) {
549 i64_udiv(n
, ten
, &n
, &digit
);
551 s
[pos
] = digit
.lo
+ '0';
557 else /* if (i64_sgn(n) == 0) */ {
561 strncpy(str
, &s
[pos
], strSize
);
564 /* Added by Paul Huxham 30/12/2000 */
566 /* Set the value of a bigint from a long */
567 bigint
i64_set( long n1
)
574 if ( n1
< 1 ) i64_inv( ret
);
579 /* Set the value of a bigint from a ulong */
580 bigint
i64_uset( unsigned long n1
)
590 /* Multiply two ulongs together and return a bigint */
591 bigint
i64_uumul( unsigned long n1
, unsigned long n2
)
598 return i64_mul( a1
, a2
);