1 /* Copyright (c) 2008 Jérémie Laval, Marine Jourdain
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 #include "biginteger.h"
30 // Private Function Impl
32 #define ATOUI(str) ((unsigned int)strtoul(buffer, NULL, 10))
33 #define MIN(x, y) (x < y ? x : y)
34 #define MAX(x, y) (x > y ? x : y)
36 BigInteger
CreateZeroBigInt()
39 temp
.Sign
= Undefined
;
40 temp
.AbsValStart
= NULL
;
41 temp
.AbsValEnd
= NULL
;
47 BigUnsignedInteger
* InitBUint(unsigned int value
)
49 BigUnsignedInteger
* bigUint
= malloc(sizeof(BigUnsignedInteger
));
50 bigUint
->Value
= value
;
55 BigUnsignedInteger
* CopyBigInteger(BigInteger source
, BigInteger
* dest
, BigUnsignedInteger
* start
, int count
)
57 BigUnsignedInteger
* node
= (start
== NULL
) ? source
.AbsValStart
: start
;
60 PushEndNode(dest
, node
->Value
);
63 } while ((node
= node
->Next
) != NULL
);
68 void Clean(BigInteger
* b
)
70 BigUnsignedInteger
* node
= b
->AbsValEnd
;
74 while (node
->Value
== 0) {
75 BigUnsignedInteger
* toFree
= node
;
76 node
= node
->Previous
;
85 // base = part1 * 10000^N + part2
86 void SplitBigInteger(int N
, BigInteger base
, BigInteger
* part1
, BigInteger
* part2
)
88 // In case N is odd part2 has a 1 more node than part1
89 int count
= (N
% 2) == 0 ? N
/2 : N
/2 + 1;
91 if (base
.Count
<= count
) {
92 // Only set part2, part1 == 0
93 /*part2->AbsValStart = base.AbsValStart;
94 part2->AbsValEnd = base.AbsValEnd;
95 part2->Count = base.Count;*/
96 CopyBigInteger(base
, part2
, NULL
, -1);
97 part2
->Sign
= Positive
;
101 BigUnsignedInteger
* node
= CopyBigInteger(base
, part2
, NULL
, count
);
102 part2
->Sign
= Positive
;
104 CopyBigInteger(base
, part1
, node
->Next
, -1);
105 part1
->Sign
= Positive
;
109 void MultiplyByBase(BigInteger
* b
, int k
)
116 void PrependNode(BigUnsignedInteger
* b1
, BigUnsignedInteger
* b2
)
122 // Used to push_front a value
123 void PushFrontNode(BigInteger
* bigInt
, unsigned int value
)
125 BigUnsignedInteger
* bigUint
= InitBUint(value
);
127 // Do the magic swapping
128 if (bigInt
->AbsValStart
!= NULL
)
129 PrependNode(bigUint
, bigInt
->AbsValStart
);
130 // Update BigInt's head field
131 bigInt
->AbsValStart
= bigUint
;
133 // If it's the first node added, correctly set bigInt->AbsValEnd
134 if (bigInt
->AbsValEnd
== NULL
)
135 bigInt
->AbsValEnd
= bigUint
;
140 void PushEndNode(BigInteger
* bigInt
, unsigned int value
)
142 BigUnsignedInteger
* buint
= InitBUint(value
);
144 // Do the magic swapping
145 if (bigInt
->AbsValEnd
!= NULL
)
146 PrependNode(bigInt
->AbsValEnd
, buint
);
147 // Update BigInt's head field
148 bigInt
->AbsValEnd
= buint
;
150 // If it's the first node added, correctly set bigInt->AbsValStart
151 if (bigInt
->AbsValStart
== NULL
)
152 bigInt
->AbsValStart
= buint
;
157 // Used to insert a node in the *middle* of the BigInt.
158 // It Do *not* check if we reproduce Push(Front|End)Node behavior
159 // Use Push(Front|End)Node if you intend to do what these functions are meant for
160 void InsertNode(BigInteger
* bigInt
, BigUnsignedInteger
* next
, unsigned int value
)
162 BigUnsignedInteger
* buint
= InitBUint(value
);
163 BigUnsignedInteger
* temp
= next
->Previous
;
165 PrependNode(buint
, next
);
166 PrependNode(temp
, buint
);
171 // End Private Function Impl
175 // Public Function Impl
177 BigInteger
newBigInteger(char* desc
)
179 int sLength
= strlen(desc
);
180 BigInteger temp
= CreateZeroBigInt();
186 temp
.Sign
= Positive
;
188 if (desc
[0] == '-' || desc
[0] == '+') {
190 temp
.Sign
= Negative
;
195 memset(buffer
, '\0', 5);
198 for (i
= sLength
- 4; i
>= startIndex
; i
-= 4) {
199 strncpy(buffer
, desc
+ i
, 4);
200 PushEndNode(&temp
, ATOUI(buffer
));
202 memset(buffer
, '\0', 5);
204 // In case the MSB digits are not packable by four do the fiddling manually
205 if (sLength
% 4 != 0) {
206 strncpy(buffer
, desc
+ startIndex
, i
+ 4 - startIndex
);
207 PushEndNode(&temp
, ATOUI(buffer
));
213 void printBigInteger(BigInteger bint
)
215 BigUnsignedInteger
* node
= bint
.AbsValEnd
;
221 if (bint
.Sign
== Negative
)
225 if (node
!= bint
.AbsValEnd
)
226 printf("%04u", node
->Value
);
228 printf("%u", node
->Value
);
229 } while((node
= node
->Previous
) != NULL
);
234 Boolean
isNull(BigInteger bint
)
236 return bint
.AbsValEnd
== NULL
? true : false;
239 int signBigInt(BigInteger bint
)
241 return (int)bint
.Sign
;
244 Boolean
equalsBigInt(BigInteger b1
, BigInteger b2
)
246 return compareBigInt(b1
, b2
) == 0 ? true : false;
253 int compareBigInt(BigInteger b1
, BigInteger b2
)
255 // try to short-circuit
256 if (b1
.Count
< b2
.Count
)
259 if (b1
.Count
> b2
.Count
)
263 BigUnsignedInteger
* node1
= b1
.AbsValEnd
;
264 BigUnsignedInteger
* node2
= b2
.AbsValEnd
;
266 // Test for NULL special case
267 if (node1
== NULL
&& node2
== NULL
)
270 if (b1
.Sign
!= b2
.Sign
) {
271 return b1
.Sign
== Negative
? -1 : 1;
275 if (node1
->Value
< node2
->Value
)
277 if (node1
->Value
> node2
->Value
)
279 } while ((node1
= node1
->Previous
) != NULL
&& (node2
= node2
->Previous
) != NULL
);
284 BigInteger
sumBigInt(BigInteger b1
, BigInteger b2
)
286 // Check some sign conditions
287 // (-b1 + b2) <=> (b2 - (+b2))
288 if (b1
.Sign
== Negative
&& b2
.Sign
== Positive
) {
290 return diffBigInt(b2
, b1
);
292 // (b1 + (-b2)) <=> (b1 - (+b2))
293 if (b1
.Sign
== Positive
&& b2
.Sign
== Negative
) {
295 return diffBigInt(b1
, b2
);
298 BigInteger result
= CreateZeroBigInt();
300 if (b1
.Sign
== Negative
&& b2
.Sign
== Negative
)
301 result
.Sign
= Negative
;
303 result
.Sign
= Positive
;
305 BigUnsignedInteger
* node1
= b1
.AbsValStart
;
306 BigUnsignedInteger
* node2
= b2
.AbsValStart
;
314 unsigned int carry
= 0;
315 Boolean cont
= false;
320 unsigned int newValue
= (node1
== NULL
? 0 : node1
->Value
) + (node2
== NULL
? 0 : node2
->Value
) + carry
;
322 carry
= newValue
/ BASE
;
323 newValue
= newValue
% BASE
;
324 PushEndNode(&result
, newValue
);
327 cont
= (node1
= node1
->Next
) != NULL
;
331 cont
= node2
!= NULL
|| cont
;
337 PushEndNode(&result
, carry
);
342 BigInteger
diffBigInt(BigInteger b1
, BigInteger b2
)
345 // -b1 - (+b2) <=> -(b1 + b2)
346 if (b1
.Sign
== Negative
&& b2
.Sign
== Positive
) {
348 return sumBigInt(b1
, b2
);
351 // b1 - (-b2) <=> b1 + b2
352 if (b1
.Sign
== Positive
&& b2
.Sign
== Negative
) {
354 return sumBigInt(b1
, b2
);
357 BigInteger result
= CreateZeroBigInt();
359 BigUnsignedInteger
* node1
= b1
.AbsValStart
;
360 BigUnsignedInteger
* node2
= b2
.AbsValStart
;
366 b2
.Sign
= b2
.Sign
== Positive
? Negative
: Positive
;
370 int comp
= compareBigInt(b1
, b2
);
373 } else if (comp
> 0) {
374 result
.Sign
= Positive
;
376 // Some magic swapping
377 result
.Sign
= Negative
;
378 BigUnsignedInteger
* temp
= node1
;
383 // Takes back the pointer value as there might have been swapping
384 // TODO : see if we can exchange directly these pointer in the if rather than b1/b2
385 /*node1 = b1.AbsValStart;
386 node2 = b2.AbsValStart;
389 unsigned int carry
= 0;
390 Boolean cont
= false;
395 unsigned int newValue
= 0;
396 if (node1
!= NULL
&& node2
!= NULL
) {
397 if (node2
->Value
> node1
->Value
) {
398 // Do a little trick to get positive coefficient
399 // and backport the changement on the upper coefficient with carry
400 newValue
= (BASE
+ node1
->Value
) - node2
->Value
- carry
;
403 newValue
= node1
->Value
- node2
->Value
- carry
;
407 // Due to our hypothethis at start of the function (test, swapping and all)
408 // we know that it's node2 which is NULL, then proceed with node1
409 newValue
= node1
->Value
- carry
;
411 // No need for unnecessary 0 in the list
416 PushEndNode(&result
, newValue
);
419 cont
= (node1
= node1
->Next
) != NULL
;
423 cont
= node2
!= NULL
|| cont
;
431 // Uses Karatsuba algorithm
432 BigInteger
mulBigInt(BigInteger x
, BigInteger y
)
434 if (x
.Sign
== 0 || y
.Sign
== 0)
435 return CreateZeroBigInt();
437 // If we have a biginteger with one node no point in further splitting
438 if (MIN(x
.Count
, y
.Count
) == 1) {
439 BigInteger temp
= CreateZeroBigInt();
440 temp
.Sign
= Positive
;
442 BigUnsignedInteger
* big
= (x
.Count
== 1) ? y
.AbsValStart
: x
.AbsValStart
;
443 unsigned int multiplier
= (x
.Count
== 1) ? x
.AbsValStart
->Value
: y
.AbsValStart
->Value
;
445 unsigned int carry
= 0;
447 while (big
!= NULL
) {
448 unsigned int r
= big
->Value
* multiplier
+ carry
;
450 PushEndNode(&temp
, r
% BASE
);
455 PushEndNode(&temp
, carry
);
460 BigInteger x0
= CreateZeroBigInt();
461 BigInteger x1
= CreateZeroBigInt();
463 BigInteger y0
= CreateZeroBigInt();
464 BigInteger y1
= CreateZeroBigInt();
466 int N
= MAX(x
.Count
, y
.Count
);
467 SplitBigInteger(N
, x
, &x1
, &x0
);
468 SplitBigInteger(N
, y
, &y1
, &y0
);
472 * c = (x1 - x0)(y1 - y0)
474 BigInteger a
= mulBigInt(x1
, y1
);
475 BigInteger b
= mulBigInt(x0
, y0
);
476 BigInteger c
= mulBigInt(diffBigInt(x1
, x0
), diffBigInt(y1
, y0
));
477 BigInteger abc
= sumBigInt(a
, b
);
478 abc
= diffBigInt(abc
, c
);
480 int k
= (N
% 2) == 0 ? N
/2 : N
/2 + 1;
481 MultiplyByBase(&a
, 2*k
);
482 MultiplyByBase(&abc
, k
);
484 BigInteger result
= sumBigInt(sumBigInt(a
, abc
), b
);
485 // Remove leading 0s if any
492 BigInteger
powBigInt(BigInteger b
, int n
)
494 BigInteger result
= b
;
496 while ((n
& 0x1) == 0) {
497 result
= mulBigInt(result
, result
);
503 result
= mulBigInt(result
, b
);
509 // End Public Function Impl