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"
29 #include "biginteger_utils.h"
31 // Private Function Impl
33 BigInteger
CreateZeroBigInt()
36 temp
.Sign
= Undefined
;
37 temp
.AbsValStart
= NULL
;
38 temp
.AbsValEnd
= NULL
;
44 BigUnsignedInteger
* InitBUint(unsigned int value
)
46 BigUnsignedInteger
* bigUint
= malloc(sizeof(BigUnsignedInteger
));
47 bigUint
->Value
= value
;
52 BigUnsignedInteger
* CopyBigInteger(BigInteger source
, BigInteger
* dest
, BigUnsignedInteger
* start
, int count
)
54 BigUnsignedInteger
* node
= (start
== NULL
) ? source
.AbsValStart
: start
;
57 PushEndNode(dest
, node
->Value
);
60 } while ((node
= node
->Next
) != NULL
);
65 BigUnsignedInteger
* CopyBigIntegerFromEnd(BigInteger source
, BigInteger
* dest
, BigUnsignedInteger
* start
, int count
)
67 BigUnsignedInteger
* node
= (start
== NULL
) ? source
.AbsValEnd
: start
;
70 PushFrontNode(dest
, node
->Value
);
73 } while ((node
= node
->Previous
) != NULL
);
78 BigUnsignedInteger
* ReplaceFromEnd(BigInteger
* source
, BigInteger slice
, BigUnsignedInteger
* start
, int count
)
83 start
= source
->AbsValEnd
;
84 source
->AbsValEnd
= slice
.AbsValEnd
;
87 /*start->Previous = slice.AbsValEnd;
88 slice.AbsValEnd->Next = start;*/
89 PrependNode(slice
.AbsValEnd
, start
);
92 BigUnsignedInteger
* endNode
= start
;
94 for (; i
<= count
&& endNode
!= NULL
; i
++)
95 endNode
= endNode
->Previous
;
97 printf("endNode is null %d\n", endNode
== NULL
);
98 if (endNode
!= NULL
) {
99 /*endNode->Next = slice.AbsValStart;
100 slice.AbsValStart->Previous = endNode;*/
101 PrependNode(endNode
, slice
.AbsValStart
);
103 source
->AbsValStart
= slice
.AbsValStart
;
106 source
->Count
-= count
;
107 source
->Count
+= slice
.Count
;
109 return slice
.AbsValEnd
->Previous
;
112 void Clean(BigInteger
* b
)
114 BigUnsignedInteger
* node
= b
->AbsValEnd
;
115 if (node
->Value
!= 0)
118 while (node
->Value
== 0) {
119 BigUnsignedInteger
* toFree
= node
;
120 node
= node
->Previous
;
130 // base = part1 * 10000^N + part2
131 void SplitBigInteger(int N
, BigInteger base
, BigInteger
* part1
, BigInteger
* part2
)
133 // In case N is odd part2 has a 1 more node than part1
134 int count
= (N
% 2) == 0 ? N
/2 : N
/2 + 1;
136 if (base
.Count
<= count
) {
137 // Only set part2, part1 == 0
138 CopyBigInteger(base
, part2
, NULL
, -1);
139 part2
->Sign
= Positive
;
143 BigUnsignedInteger
* node
= CopyBigInteger(base
, part2
, NULL
, count
);
144 part2
->Sign
= Positive
;
146 CopyBigInteger(base
, part1
, node
->Next
, -1);
147 part1
->Sign
= Positive
;
151 void MultiplyByBase(BigInteger
* b
, int k
)
158 void PrependNode(BigUnsignedInteger
* b1
, BigUnsignedInteger
* b2
)
164 // Used to push_front a value
165 void PushFrontNode(BigInteger
* bigInt
, unsigned int value
)
167 BigUnsignedInteger
* bigUint
= InitBUint(value
);
169 // Do the magic swapping
170 if (bigInt
->AbsValStart
!= NULL
)
171 PrependNode(bigUint
, bigInt
->AbsValStart
);
172 // Update BigInt's head field
173 bigInt
->AbsValStart
= bigUint
;
175 // If it's the first node added, correctly set bigInt->AbsValEnd
176 if (bigInt
->AbsValEnd
== NULL
)
177 bigInt
->AbsValEnd
= bigUint
;
182 void PushEndNode(BigInteger
* bigInt
, unsigned int value
)
184 BigUnsignedInteger
* buint
= InitBUint(value
);
186 // Do the magic swapping
187 if (bigInt
->AbsValEnd
!= NULL
)
188 PrependNode(bigInt
->AbsValEnd
, buint
);
189 // Update BigInt's head field
190 bigInt
->AbsValEnd
= buint
;
192 // If it's the first node added, correctly set bigInt->AbsValStart
193 if (bigInt
->AbsValStart
== NULL
)
194 bigInt
->AbsValStart
= buint
;
199 void PopFrontNode(BigInteger
* bigInt
)
203 BigUnsignedInteger
* node
= bigInt
->AbsValStart
;
204 node
->Next
->Previous
= NULL
;
205 bigInt
->AbsValStart
= node
->Next
;
210 void PopEndNode(BigInteger
* bigInt
)
214 BigUnsignedInteger
* node
= bigInt
->AbsValEnd
;
215 node
->Previous
->Next
= NULL
;
216 bigInt
->AbsValEnd
= node
->Previous
;
222 // Used to insert a node in the *middle* of the BigInt.
223 // It Do *not* check if we reproduce Push(Front|End)Node behavior
224 // Use Push(Front|End)Node if you intend to do what these functions are meant for
225 void InsertNode(BigInteger
* bigInt
, BigUnsignedInteger
* next
, unsigned int value
)
227 BigUnsignedInteger
* buint
= InitBUint(value
);
228 BigUnsignedInteger
* temp
= next
->Previous
;
230 PrependNode(buint
, next
);
231 PrependNode(temp
, buint
);
236 unsigned int GetValueAtFromEnd(BigInteger b
, int index
)
238 BigUnsignedInteger
* node
= b
.AbsValEnd
;
241 for (; i
< index
; i
++) {
244 node
= node
->Previous
;
249 BigInteger
mulBigIntByScalar(BigUnsignedInteger
* big
, unsigned int multiplier
)
251 BigInteger temp
= CreateZeroBigInt();
252 unsigned int carry
= 0;
254 // Multiplied bigint supposed to be positive
255 temp
.Sign
= multiplier
< 0 ? Negative
: Positive
;
257 while (big
!= NULL
) {
258 unsigned int r
= big
->Value
* multiplier
+ carry
;
260 PushEndNode(&temp
, r
% BASE
);
265 PushEndNode(&temp
, carry
);
271 BigInteger
powBigInt(BigInteger b
, int n
)
273 BigInteger result
= b
;
275 while ((n
& 0x1) == 0) {
276 result
= mulBigInt(result
, result
);
282 result
= mulBigInt(result
, b
);
289 // End Private Function Impl