Merge branch 'reorganization'
[biginteger-lo27.git] / biginteger_utils.c
blobcd6092eb1fb736a52a32527304df50df7bf34fdd
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
19 * THE SOFTWARE.
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include <string.h>
28 #include "biginteger.h"
29 #include "biginteger_utils.h"
31 // Private Function Impl
33 BigInteger CreateZeroBigInt()
35 BigInteger temp;
36 temp.Sign = Undefined;
37 temp.AbsValStart = NULL;
38 temp.AbsValEnd = NULL;
39 temp.Count = 0;
41 return temp;
44 BigUnsignedInteger* InitBUint(unsigned int value)
46 BigUnsignedInteger* bigUint = malloc(sizeof(BigUnsignedInteger));
47 bigUint->Value = value;
49 return bigUint;
52 BigUnsignedInteger* CopyBigInteger(BigInteger source, BigInteger* dest, BigUnsignedInteger* start, int count)
54 BigUnsignedInteger* node = (start == NULL) ? source.AbsValStart : start;
56 do {
57 PushEndNode(dest, node->Value);
58 if (--count == 0)
59 break;
60 } while ((node = node->Next) != NULL);
62 return node;
65 BigUnsignedInteger* CopyBigIntegerFromEnd(BigInteger source, BigInteger* dest, BigUnsignedInteger* start, int count)
67 BigUnsignedInteger* node = (start == NULL) ? source.AbsValEnd : start;
69 do {
70 PushFrontNode(dest, node->Value);
71 if (--count == 0)
72 break;
73 } while ((node = node->Previous) != NULL);
75 return node;
78 BigUnsignedInteger* ReplaceFromEnd(BigInteger* source, BigInteger slice, BigUnsignedInteger* start, int count)
80 if (start == NULL) {
81 source->AbsValEnd = slice.AbsValEnd;
82 start = source->AbsValEnd;
83 } else {
84 start->Previous = slice.AbsValEnd;
87 BigUnsignedInteger* endNode = start;
88 int i;
89 for (i = 0; i < count; i++)
90 endNode = endNode->Previous;
92 if (endNode != NULL) {
93 endNode->Next = slice.AbsValStart;
94 } else {
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)
108 return;
110 while (node->Value == 0) {
111 BigUnsignedInteger* toFree = node;
112 node = node->Previous;
113 free(toFree);
116 // Erase things up
117 b->AbsValEnd = node;
118 node->Next = NULL;
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;
131 return;
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)
144 int i = 0;
145 for (; i < k; i++)
146 PushFrontNode(b, 0);
149 void PrependNode(BigUnsignedInteger* b1, BigUnsignedInteger* b2)
151 b1->Next = b2;
152 b2->Previous = b1;
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;
170 bigInt->Count++;
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;
187 bigInt->Count++;
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);
201 bigInt->Count++;
204 unsigned int GetValueAtFromEnd(BigInteger b, int index)
206 BigUnsignedInteger* node = b.AbsValEnd;
208 int i = 0;
209 for (; i < index; i++) {
210 if (node == NULL)
211 return 0;
212 node = node->Previous;
214 return node->Value;
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;
224 carry = r / BASE;
225 PushEndNode(&temp, r % BASE);
227 big = big->Next;
229 if (carry != 0)
230 PushEndNode(&temp, carry);
232 return temp;
235 // Returns b^n
236 BigInteger powBigInt(BigInteger b, int n)
238 BigInteger result = b;
240 while ((n & 0x1) == 0) {
241 result = mulBigInt(result, result);
242 n /= 2;
244 if (n != 1) {
245 int i = n;
246 for (; i >= 1; i--)
247 result = mulBigInt(result, b);
250 return result;
254 // End Private Function Impl