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 // base = part1 * 10000^N + part2
69 void SplitBigInteger(int N
, BigInteger base
, BigInteger
* part1
, BigInteger
* part2
)
71 // In case N is odd part2 has a 1 more node than part1
72 int count
= (N
% 2) == 0 ? N
/2 : N
/2 + 1;
74 if (base
.Count
<= count
) {
75 // Only set part2, part1 == 0
76 /*part2->AbsValStart = base.AbsValStart;
77 part2->AbsValEnd = base.AbsValEnd;
78 part2->Count = base.Count;*/
79 CopyBigInteger(base
, part2
, NULL
, -1);
80 part2
->Sign
= Positive
;
84 BigUnsignedInteger
* node
= CopyBigInteger(base
, part2
, NULL
, count
);
85 part2
->Sign
= Positive
;
87 CopyBigInteger(base
, part1
, node
->Next
, -1);
88 part1
->Sign
= Positive
;
92 void MultiplyByBase(BigInteger
* b
, int k
)
99 void PrependNode(BigUnsignedInteger
* b1
, BigUnsignedInteger
* b2
)
105 // Used to push_front a value
106 void PushFrontNode(BigInteger
* bigInt
, unsigned int value
)
108 BigUnsignedInteger
* bigUint
= InitBUint(value
);
110 // Do the magic swapping
111 if (bigInt
->AbsValStart
!= NULL
)
112 PrependNode(bigUint
, bigInt
->AbsValStart
);
113 // Update BigInt's head field
114 bigInt
->AbsValStart
= bigUint
;
116 // If it's the first node added, correctly set bigInt->AbsValEnd
117 if (bigInt
->AbsValEnd
== NULL
)
118 bigInt
->AbsValEnd
= bigUint
;
123 void PushEndNode(BigInteger
* bigInt
, unsigned int value
)
125 BigUnsignedInteger
* buint
= InitBUint(value
);
127 // Do the magic swapping
128 if (bigInt
->AbsValEnd
!= NULL
)
129 PrependNode(bigInt
->AbsValEnd
, buint
);
130 // Update BigInt's head field
131 bigInt
->AbsValEnd
= buint
;
133 // If it's the first node added, correctly set bigInt->AbsValStart
134 if (bigInt
->AbsValStart
== NULL
)
135 bigInt
->AbsValStart
= buint
;
140 // Used to insert a node in the *middle* of the BigInt.
141 // It Do *not* check if we reproduce Push(Front|End)Node behavior
142 // Use Push(Front|End)Node if you intend to do what these functions are meant for
143 void InsertNode(BigInteger
* bigInt
, BigUnsignedInteger
* next
, unsigned int value
)
145 BigUnsignedInteger
* buint
= InitBUint(value
);
146 BigUnsignedInteger
* temp
= next
->Previous
;
148 PrependNode(buint
, next
);
149 PrependNode(temp
, buint
);
154 // End Private Function Impl
158 // Public Function Impl
160 BigInteger
newBigInteger(char* desc
)
162 int sLength
= strlen(desc
);
163 BigInteger temp
= CreateZeroBigInt();
169 temp
.Sign
= Positive
;
171 if (desc
[0] == '-' || desc
[0] == '+') {
173 temp
.Sign
= Negative
;
178 memset(buffer
, '\0', 5);
181 for (i
= sLength
- 4; i
>= startIndex
; i
-= 4) {
182 strncpy(buffer
, desc
+ i
, 4);
183 PushEndNode(&temp
, ATOUI(buffer
));
185 memset(buffer
, '\0', 5);
187 // In case the MSB digits are not packable by four do the fiddling manually
188 if (sLength
% 4 != 0) {
189 strncpy(buffer
, desc
+ startIndex
, i
+ 4 - startIndex
);
190 PushEndNode(&temp
, ATOUI(buffer
));
196 void printBigInteger(BigInteger bint
)
198 BigUnsignedInteger
* node
= bint
.AbsValEnd
;
204 if (bint
.Sign
== Negative
)
208 if (node
!= bint
.AbsValEnd
)
209 printf("%04u", node
->Value
);
211 printf("%u", node
->Value
);
212 } while((node
= node
->Previous
) != NULL
);
217 Boolean
isNull(BigInteger bint
)
219 return bint
.AbsValEnd
== NULL
? true : false;
222 int signBigInt(BigInteger bint
)
224 return (int)bint
.Sign
;
227 Boolean
equalsBigInt(BigInteger b1
, BigInteger b2
)
229 return compareBigInt(b1
, b2
) == 0 ? true : false;
236 int compareBigInt(BigInteger b1
, BigInteger b2
)
238 // try to short-circuit
239 if (b1
.Count
< b2
.Count
)
242 if (b1
.Count
> b2
.Count
)
246 BigUnsignedInteger
* node1
= b1
.AbsValEnd
;
247 BigUnsignedInteger
* node2
= b2
.AbsValEnd
;
249 // Test for NULL special case
250 if (node1
== NULL
&& node2
== NULL
)
253 if (b1
.Sign
!= b2
.Sign
) {
254 return b1
.Sign
== Negative
? -1 : 1;
258 if (node1
->Value
< node2
->Value
)
260 if (node1
->Value
> node2
->Value
)
262 } while ((node1
= node1
->Previous
) != NULL
&& (node2
= node2
->Previous
) != NULL
);
267 BigInteger
sumBigInt(BigInteger b1
, BigInteger b2
)
269 // Check some sign conditions
270 // (-b1 + b2) <=> (b2 - (+b2))
271 if (b1
.Sign
== Negative
&& b2
.Sign
== Positive
) {
273 return diffBigInt(b2
, b1
);
275 // (b1 + (-b2)) <=> (b1 - (+b2))
276 if (b1
.Sign
== Positive
&& b2
.Sign
== Negative
) {
278 return diffBigInt(b1
, b2
);
281 BigInteger result
= CreateZeroBigInt();
283 if (b1
.Sign
== Negative
&& b2
.Sign
== Negative
)
284 result
.Sign
= Negative
;
286 result
.Sign
= Positive
;
288 BigUnsignedInteger
* node1
= b1
.AbsValStart
;
289 BigUnsignedInteger
* node2
= b2
.AbsValStart
;
297 unsigned int carry
= 0;
298 Boolean cont
= false;
303 unsigned int newValue
= (node1
== NULL
? 0 : node1
->Value
) + (node2
== NULL
? 0 : node2
->Value
) + carry
;
305 carry
= newValue
/ BASE
;
306 newValue
= newValue
% BASE
;
307 PushEndNode(&result
, newValue
);
310 cont
= (node1
= node1
->Next
) != NULL
;
314 cont
= node2
!= NULL
|| cont
;
317 if (!cont
&& carry
> 0)
318 PushEndNode(&result
, carry
);
324 BigInteger
diffBigInt(BigInteger b1
, BigInteger b2
)
327 // -b1 - (+b2) <=> -(b1 + b2)
328 if (b1
.Sign
== Negative
&& b2
.Sign
== Positive
) {
330 return sumBigInt(b1
, b2
);
333 // b1 - (-b2) <=> b1 + b2
334 if (b1
.Sign
== Positive
&& b2
.Sign
== Negative
) {
336 return sumBigInt(b1
, b2
);
339 BigInteger result
= CreateZeroBigInt();
341 BigUnsignedInteger
* node1
= b1
.AbsValStart
;
342 BigUnsignedInteger
* node2
= b2
.AbsValStart
;
348 b2
.Sign
= b2
.Sign
== Positive
? Negative
: Positive
;
352 int comp
= compareBigInt(b1
, b2
);
355 } else if (comp
> 0) {
356 result
.Sign
= Positive
;
358 // Some magic swapping
359 result
.Sign
= Negative
;
360 BigUnsignedInteger
* temp
= node1
;
365 // Takes back the pointer value as there might have been swapping
366 // TODO : see if we can exchange directly these pointer in the if rather than b1/b2
367 /*node1 = b1.AbsValStart;
368 node2 = b2.AbsValStart;
371 unsigned int carry
= 0;
372 Boolean cont
= false;
377 unsigned int newValue
= 0;
378 if (node1
!= NULL
&& node2
!= NULL
) {
379 if (node2
->Value
> node1
->Value
) {
380 // Do a little trick to get positive coefficient
381 // and backport the changement on the upper coefficient with carry
382 newValue
= (BASE
+ node1
->Value
) - node2
->Value
- carry
;
385 newValue
= node1
->Value
- node2
->Value
- carry
;
389 // Due to our hypothethis at start of the function (test, swapping and all)
390 // we know that it's node2 which is NULL, then proceed with node1
391 newValue
= node1
->Value
- carry
;
393 // No need for unnecessary 0 in the list
398 PushEndNode(&result
, newValue
);
401 cont
= (node1
= node1
->Next
) != NULL
;
405 cont
= node2
!= NULL
|| cont
;
413 // Uses Karatsuba algorithm
414 BigInteger
mulBigInt(BigInteger x
, BigInteger y
)
416 if (x
.Sign
== 0 || y
.Sign
== 0)
417 return CreateZeroBigInt();
419 if (MAX(x
.Count
, y
.Count
) == 1) {
420 BigInteger temp
= CreateZeroBigInt();
421 temp
.Sign
= Positive
;
423 unsigned int result
= x
.AbsValStart
->Value
* y
.AbsValStart
->Value
;
424 if (result
/ BASE
!= 0)
425 PushFrontNode(&temp
, result
/ BASE
);
426 PushFrontNode(&temp
, result
% BASE
);
430 BigInteger x0
= CreateZeroBigInt();
431 BigInteger x1
= CreateZeroBigInt();
433 BigInteger y0
= CreateZeroBigInt();
434 BigInteger y1
= CreateZeroBigInt();
436 int N
= MAX(x
.Count
, y
.Count
);
437 SplitBigInteger(N
, x
, &x1
, &x0
);
438 SplitBigInteger(N
, y
, &y1
, &y0
);
442 * c = (x1 - x0)(y1 - y0)
444 BigInteger a
= mulBigInt(x1
, y1
);
445 BigInteger b
= mulBigInt(x0
, y0
);
446 BigInteger c
= mulBigInt(diffBigInt(x1
, x0
), diffBigInt(y1
, y0
));
447 BigInteger abc
= sumBigInt(a
, b
);
448 abc
= diffBigInt(abc
, c
);
450 int k
= (N
% 2) == 0 ? N
/2 : N
/2 + 1;
451 MultiplyByBase(&a
, 2*k
);
452 MultiplyByBase(&abc
, k
);
454 return sumBigInt(sumBigInt(a
, abc
), b
);
458 BigInteger
powBigInt(BigInteger b
, int n
)
460 BigInteger result
= b
;
462 while ((n
& 0x1) == 0) {
463 result
= mulBigInt(result
, result
);
469 result
= mulBigInt(result
, b
);
475 // End Public Function Impl