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
)
81 source
->AbsValEnd
= slice
.AbsValEnd
;
82 start
= source
->AbsValEnd
;
84 start
->Previous
= slice
.AbsValEnd
;
87 BigUnsignedInteger
* endNode
= start
;
89 for (i
= 0; i
< count
; i
++)
90 endNode
= endNode
->Previous
;
92 if (endNode
!= NULL
) {
93 endNode
->Next
= slice
.AbsValStart
;
95 source
->AbsValStart
= slice
.AbsValStart
;
98 source
->Count
-= count
;
99 source
->Count
+= slice
.Count
;
101 return slice
.AbsValEnd
->Previous
;
104 void Clean(BigInteger
* b
)
106 BigUnsignedInteger
* node
= b
->AbsValEnd
;
107 if (node
->Value
!= 0)
110 while (node
->Value
== 0) {
111 BigUnsignedInteger
* toFree
= node
;
112 node
= node
->Previous
;
121 // base = part1 * 10000^N + part2
122 void SplitBigInteger(int N
, BigInteger base
, BigInteger
* part1
, BigInteger
* part2
)
124 // In case N is odd part2 has a 1 more node than part1
125 int count
= (N
% 2) == 0 ? N
/2 : N
/2 + 1;
127 if (base
.Count
<= count
) {
128 // Only set part2, part1 == 0
129 CopyBigInteger(base
, part2
, NULL
, -1);
130 part2
->Sign
= Positive
;
134 BigUnsignedInteger
* node
= CopyBigInteger(base
, part2
, NULL
, count
);
135 part2
->Sign
= Positive
;
137 CopyBigInteger(base
, part1
, node
->Next
, -1);
138 part1
->Sign
= Positive
;
142 void MultiplyByBase(BigInteger
* b
, int k
)
149 void PrependNode(BigUnsignedInteger
* b1
, BigUnsignedInteger
* b2
)
155 // Used to push_front a value
156 void PushFrontNode(BigInteger
* bigInt
, unsigned int value
)
158 BigUnsignedInteger
* bigUint
= InitBUint(value
);
160 // Do the magic swapping
161 if (bigInt
->AbsValStart
!= NULL
)
162 PrependNode(bigUint
, bigInt
->AbsValStart
);
163 // Update BigInt's head field
164 bigInt
->AbsValStart
= bigUint
;
166 // If it's the first node added, correctly set bigInt->AbsValEnd
167 if (bigInt
->AbsValEnd
== NULL
)
168 bigInt
->AbsValEnd
= bigUint
;
173 void PushEndNode(BigInteger
* bigInt
, unsigned int value
)
175 BigUnsignedInteger
* buint
= InitBUint(value
);
177 // Do the magic swapping
178 if (bigInt
->AbsValEnd
!= NULL
)
179 PrependNode(bigInt
->AbsValEnd
, buint
);
180 // Update BigInt's head field
181 bigInt
->AbsValEnd
= buint
;
183 // If it's the first node added, correctly set bigInt->AbsValStart
184 if (bigInt
->AbsValStart
== NULL
)
185 bigInt
->AbsValStart
= buint
;
190 // Used to insert a node in the *middle* of the BigInt.
191 // It Do *not* check if we reproduce Push(Front|End)Node behavior
192 // Use Push(Front|End)Node if you intend to do what these functions are meant for
193 void InsertNode(BigInteger
* bigInt
, BigUnsignedInteger
* next
, unsigned int value
)
195 BigUnsignedInteger
* buint
= InitBUint(value
);
196 BigUnsignedInteger
* temp
= next
->Previous
;
198 PrependNode(buint
, next
);
199 PrependNode(temp
, buint
);
204 unsigned int GetValueAtFromEnd(BigInteger b
, int index
)
206 BigUnsignedInteger
* node
= b
.AbsValEnd
;
209 for (; i
< index
; i
++) {
212 node
= node
->Previous
;
217 BigInteger
mulBigIntByScalar(BigUnsignedInteger
* big
, unsigned int multiplier
)
219 BigInteger temp
= CreateZeroBigInt();
220 unsigned int carry
= 0;
222 while (big
!= NULL
) {
223 unsigned int r
= big
->Value
* multiplier
+ carry
;
225 PushEndNode(&temp
, r
% BASE
);
230 PushEndNode(&temp
, carry
);
236 BigInteger
powBigInt(BigInteger b
, int n
)
238 BigInteger result
= b
;
240 while ((n
& 0x1) == 0) {
241 result
= mulBigInt(result
, result
);
247 result
= mulBigInt(result
, b
);
254 // End Private Function Impl