1 /* Based on https://github.com/kokke/tiny-bignum-c.
2 * Enjoy it --FXTi
3 */
4
5 #include <r_util.h>
6
7 /* Functions for shifting number in-place. */
8 static void _lshift_one_bit(RNumBig *a);
9 static void _rshift_one_bit(RNumBig *a);
10 static void _lshift_word(RNumBig *a, int nwords);
11 static void _rshift_word(RNumBig *a, int nwords);
12 static void _r_big_zero_out(RNumBig *n);
13
r_big_new(void)14 R_API RNumBig *r_big_new(void) {
15 RNumBig *n = R_NEW (RNumBig);
16 if (n) {
17 _r_big_zero_out (n);
18 }
19 return n;
20 }
21
r_big_free(RNumBig * b)22 R_API void r_big_free(RNumBig *b) {
23 free (b);
24 }
25
r_big_init(RNumBig * b)26 R_API void r_big_init(RNumBig *b) {
27 _r_big_zero_out (b);
28 }
29
r_big_fini(RNumBig * b)30 R_API void r_big_fini(RNumBig *b) {
31 _r_big_zero_out (b);
32 }
33
r_big_from_int(RNumBig * b,st64 n)34 R_API void r_big_from_int(RNumBig *b, st64 n) {
35 r_return_if_fail (b);
36
37 _r_big_zero_out (b);
38 b->sign = (n < 0)? -1: 1;
39 R_BIG_DTYPE_TMP v = n * b->sign;
40
41 /* Endianness issue if machine is not little-endian? */
42 #ifdef R_BIG_WORD_SIZE
43 #if (R_BIG_WORD_SIZE == 1)
44 b->array[0] = (v & 0x000000ff);
45 b->array[1] = (v & 0x0000ff00) >> 8;
46 b->array[2] = (v & 0x00ff0000) >> 16;
47 b->array[3] = (v & 0xff000000) >> 24;
48 #elif (R_BIG_WORD_SIZE == 2)
49 b->array[0] = (v & 0x0000ffff);
50 b->array[1] = (v & 0xffff0000) >> 16;
51 #elif (R_BIG_WORD_SIZE == 4)
52 b->array[0] = v;
53 R_BIG_DTYPE_TMP num_32 = 32;
54 R_BIG_DTYPE_TMP tmp = v >> num_32;
55 b->array[1] = tmp;
56 #endif
57 #endif
58 }
59
r_big_from_unsigned(RNumBig * b,ut64 v)60 static void r_big_from_unsigned(RNumBig *b, ut64 v) {
61 r_return_if_fail (b);
62
63 _r_big_zero_out (b);
64
65 /* Endianness issue if machine is not little-endian? */
66 #ifdef R_BIG_WORD_SIZE
67 #if (R_BIG_WORD_SIZE == 1)
68 b->array[0] = (v & 0x000000ff);
69 b->array[1] = (v & 0x0000ff00) >> 8;
70 b->array[2] = (v & 0x00ff0000) >> 16;
71 b->array[3] = (v & 0xff000000) >> 24;
72 #elif (R_BIG_WORD_SIZE == 2)
73 b->array[0] = (v & 0x0000ffff);
74 b->array[1] = (v & 0xffff0000) >> 16;
75 #elif (R_BIG_WORD_SIZE == 4)
76 b->array[0] = v;
77 R_BIG_DTYPE_TMP num_32 = 32;
78 R_BIG_DTYPE_TMP tmp = v >> num_32;
79 b->array[1] = tmp;
80 #endif
81 #endif
82 }
83
r_big_to_int(RNumBig * b)84 R_API st64 r_big_to_int(RNumBig *b) {
85 r_return_val_if_fail (b, 0);
86
87 R_BIG_DTYPE_TMP ret = 0;
88
89 /* Endianness issue if machine is not little-endian? */
90 #if (R_BIG_WORD_SIZE == 1)
91 ret += b->array[0];
92 ret += b->array[1] << 8;
93 ret += b->array[2] << 16;
94 ret += b->array[3] << 24;
95 #elif (R_BIG_WORD_SIZE == 2)
96 ret += b->array[0];
97 ret += b->array[1] << 16;
98 #elif (R_BIG_WORD_SIZE == 4)
99 ret += b->array[1];
100 ret <<= 32;
101 ret += b->array[0];
102 #endif
103
104 if (b->sign < 0) {
105 return -ret;
106 }
107 return ret;
108 }
109
r_big_from_hexstr(RNumBig * n,const char * str)110 R_API void r_big_from_hexstr(RNumBig *n, const char *str) {
111 r_return_if_fail (n);
112 r_return_if_fail (str);
113 int nbytes = strlen (str);
114
115 _r_big_zero_out (n);
116
117 if (str[0] == '-') {
118 n->sign = -1;
119 str += 1;
120 nbytes -= 1;
121 }
122
123 if (str[0] == '0' && str[1] == 'x') {
124 str += 2;
125 nbytes -= 2;
126 }
127 r_return_if_fail (nbytes > 0);
128
129 R_BIG_DTYPE tmp;
130 int i = nbytes - (2 * R_BIG_WORD_SIZE); /* index into string */
131 int j = 0; /* index into array */
132
133 while (i >= 0) {
134 tmp = 0;
135 sscanf (&str[i], R_BIG_SSCANF_FORMAT_STR, &tmp);
136 n->array[j] = tmp;
137 i -= (2 * R_BIG_WORD_SIZE); /* step R_BIG_WORD_SIZE hex-byte(s) back in the string. */
138 j += 1; /* step one element forward in the array. */
139 }
140
141 if (-2 * R_BIG_WORD_SIZE < i) {
142 char buffer[2 * R_BIG_WORD_SIZE];
143 memset (buffer, 0, sizeof (buffer));
144 i += 2 * R_BIG_WORD_SIZE - 1;
145 for (; i >= 0; i--) {
146 buffer[i] = str[i];
147 }
148 tmp = 0;
149 sscanf (buffer, R_BIG_SSCANF_FORMAT_STR, &tmp);
150 n->array[j] = tmp;
151 }
152 }
153
r_big_to_hexstr(RNumBig * b)154 R_API char *r_big_to_hexstr(RNumBig *b) {
155 r_return_val_if_fail (b, NULL);
156
157 int j = R_BIG_ARRAY_SIZE - 1; /* index into array - reading "MSB" first -> big-endian */
158 size_t i = 0; /* index into string representation. */
159 size_t k = 0; /* Leading zero's amount */
160 size_t z, last_z = 2 * R_BIG_WORD_SIZE;
161
162 for (; b->array[j] == 0 && j >= 0; j--) {
163 }
164 if (j == -1) {
165 return "0x0";
166 }
167
168 size_t size = 3 + 2 * R_BIG_WORD_SIZE * (j + 1) + ((b->sign > 0)? 0: 1);
169 char *ret_str = calloc (size, sizeof (char));
170 if (!ret_str) {
171 return NULL;
172 }
173
174 if (b->sign < 0) {
175 ret_str[i++] = '-';
176 }
177 ret_str[i++] = '0';
178 ret_str[i++] = 'x';
179
180 r_snprintf (ret_str + i, R_BIG_FORMAT_STR_LEN, R_BIG_SPRINTF_FORMAT_STR, b->array[j--]);
181 for (; ret_str[i + k] == '0' && k < 2 * R_BIG_WORD_SIZE; k++) {
182 }
183 for (z = k; ret_str[i + z] && z < last_z; z++) {
184 ret_str[i + z - k] = ret_str[i + z];
185 }
186 i += z - k;
187 ret_str[i] = '\x00'; // Truncate string for case(j < 0)
188
189 for (; j >= 0; j--) {
190 r_snprintf (ret_str + i, R_BIG_FORMAT_STR_LEN, R_BIG_SPRINTF_FORMAT_STR, b->array[j]);
191 i += 2 * R_BIG_WORD_SIZE;
192 }
193
194 return ret_str;
195 }
196
r_big_assign(RNumBig * dst,RNumBig * src)197 R_API void r_big_assign(RNumBig *dst, RNumBig *src) {
198 r_return_if_fail (dst);
199 r_return_if_fail (src);
200
201 memcpy (dst, src, sizeof (RNumBig));
202 }
203
r_big_add_inner(RNumBig * c,RNumBig * a,RNumBig * b)204 static void r_big_add_inner(RNumBig *c, RNumBig *a, RNumBig *b) {
205 R_BIG_DTYPE_TMP tmp;
206 int carry = 0;
207 int i;
208 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
209 tmp = (R_BIG_DTYPE_TMP)a->array[i] + b->array[i] + carry;
210 carry = (tmp > R_BIG_MAX_VAL);
211 c->array[i] = (tmp & R_BIG_MAX_VAL);
212 }
213 }
214
r_big_sub_inner(RNumBig * c,RNumBig * a,RNumBig * b)215 static void r_big_sub_inner(RNumBig *c, RNumBig *a, RNumBig *b) {
216 R_BIG_DTYPE_TMP res;
217 RNumBig *tmp;
218 R_BIG_DTYPE_TMP tmp1;
219 R_BIG_DTYPE_TMP tmp2;
220 int borrow = 0;
221 int sign = r_big_cmp (a, b);
222 c->sign = (sign >= 0? 1: -1);
223 if (sign < 0) {
224 tmp = a;
225 a = b;
226 b = tmp;
227 }
228 int i;
229 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
230 tmp1 = (R_BIG_DTYPE_TMP)a->array[i] + (R_BIG_MAX_VAL + 1); /* + number_base */
231 tmp2 = (R_BIG_DTYPE_TMP)b->array[i] + borrow;
232
233 res = (tmp1 - tmp2);
234 c->array[i] = (R_BIG_DTYPE) (res & R_BIG_MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if nu mber_base is 2^N */
235 borrow = (res <= R_BIG_MAX_VAL);
236 }
237 }
238
r_big_add(RNumBig * c,RNumBig * a,RNumBig * b)239 R_API void r_big_add(RNumBig *c, RNumBig *a, RNumBig *b) {
240 r_return_if_fail (a);
241 r_return_if_fail (b);
242 r_return_if_fail (c);
243
244 if (a->sign >= 0 && b->sign >= 0) {
245 r_big_add_inner (c, a, b);
246 c->sign = 1;
247 return;
248 }
249 if (a->sign >= 0 && b->sign < 0) {
250 r_big_sub_inner (c, a, b);
251 return;
252 }
253 if (a->sign < 0 && b->sign >= 0) {
254 r_big_sub_inner (c, b, a);
255 return;
256 }
257 if (a->sign < 0 && b->sign < 0) {
258 r_big_add_inner (c, a, b);
259 c->sign = -1;
260 return;
261 }
262 }
263
r_big_sub(RNumBig * c,RNumBig * a,RNumBig * b)264 R_API void r_big_sub(RNumBig *c, RNumBig *a, RNumBig *b) {
265 r_return_if_fail (a);
266 r_return_if_fail (b);
267 r_return_if_fail (c);
268
269 if (a->sign >= 0 && b->sign >= 0) {
270 r_big_sub_inner (c, a, b);
271 return;
272 }
273 if (a->sign >= 0 && b->sign < 0) {
274 r_big_add_inner (c, a, b);
275 c->sign = 1;
276 return;
277 }
278 if (a->sign < 0 && b->sign >= 0) {
279 r_big_add_inner (c, a, b);
280 c->sign = -1;
281 return;
282 }
283 if (a->sign < 0 && b->sign < 0) {
284 r_big_sub_inner (c, b, a);
285 return;
286 }
287 }
288
r_big_mul(RNumBig * c,RNumBig * a,RNumBig * b)289 R_API void r_big_mul(RNumBig *c, RNumBig *a, RNumBig *b) {
290 r_return_if_fail (a);
291 r_return_if_fail (b);
292 r_return_if_fail (c);
293
294 RNumBig *row = r_big_new ();
295 RNumBig *tmp = r_big_new ();
296 RNumBig *res = r_big_new ();
297 int i, j;
298
299 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
300 _r_big_zero_out (row);
301
302 for (j = 0; j < R_BIG_ARRAY_SIZE; j++) {
303 if (i + j < R_BIG_ARRAY_SIZE) {
304 _r_big_zero_out (tmp);
305 R_BIG_DTYPE_TMP intermediate = ((R_BIG_DTYPE_TMP)a->array[i] * (R_BIG_DTYPE_TMP)b->array[j]);
306 r_big_from_unsigned (tmp, intermediate);
307 _lshift_word (tmp, i + j);
308 r_big_add (row, row, tmp);
309 }
310 }
311 r_big_add (res, row, res);
312 }
313
314 res->sign = a->sign * b->sign;
315 if (r_big_is_zero (res)) {
316 res->sign = 1; // For -1 * 0 case
317 }
318 r_big_assign (c, res);
319
320 r_big_free (row);
321 r_big_free (tmp);
322 r_big_free (res);
323 }
324
r_big_div(RNumBig * c,RNumBig * a,RNumBig * b)325 R_API void r_big_div(RNumBig *c, RNumBig *a, RNumBig *b) {
326 r_return_if_fail (a);
327 r_return_if_fail (b);
328 r_return_if_fail (c);
329 r_return_if_fail (!r_big_is_zero (b));
330
331 RNumBig *current = r_big_new ();
332 RNumBig *denom = r_big_new ();
333 ;
334 RNumBig *tmp = r_big_new ();
335 int sign = a->sign * b->sign;
336
337 r_big_from_int (current, 1); // int current = 1;
338 r_big_assign (denom, b); // denom = b
339 denom->sign = 1;
340 r_big_assign (tmp, denom); // tmp = denom = b
341 _lshift_one_bit (tmp); // tmp <= 1
342
343 while (r_big_cmp (tmp, a) != 1) { // while (tmp <= a)
344 if ((denom->array[R_BIG_ARRAY_SIZE - 1] >> (R_BIG_WORD_SIZE * 8 - 1)) == 1) {
345 break; // Reach the max value
346 }
347 _lshift_one_bit (tmp); // tmp <= 1
348 _lshift_one_bit (denom); // denom <= 1
349 _lshift_one_bit (current); // current <= 1
350 }
351
352 r_big_assign (tmp, a); // tmp = a
353 tmp->sign = 1;
354 _r_big_zero_out (c); // int answer = 0;
355
356 while (!r_big_is_zero (current)) // while (current != 0)
357 {
358 if (r_big_cmp (tmp, denom) != -1) // if (dividend >= denom)
359 {
360 r_big_sub (tmp, tmp, denom); // dividend -= denom;
361 r_big_or (c, current, c); // answer |= current;
362 }
363 _rshift_one_bit (current); // current >>= 1;
364 _rshift_one_bit (denom); // denom >>= 1;
365 } // return answer;
366
367 c->sign = sign;
368 if (r_big_is_zero (c)) {
369 c->sign = 1; // For -1 * 0 case
370 }
371 r_big_free (current);
372 r_big_free (denom);
373 r_big_free (tmp);
374 }
375
r_big_mod(RNumBig * c,RNumBig * a,RNumBig * b)376 R_API void r_big_mod(RNumBig *c, RNumBig *a, RNumBig *b) {
377 /*
378 Take divmod and throw away div part
379 */
380 r_return_if_fail (a);
381 r_return_if_fail (b);
382 r_return_if_fail (c);
383 r_return_if_fail (!r_big_is_zero (b));
384
385 RNumBig *tmp = r_big_new ();
386
387 r_big_divmod (tmp, c, a, b);
388
389 r_big_free (tmp);
390 }
391
r_big_divmod(RNumBig * c,RNumBig * d,RNumBig * a,RNumBig * b)392 R_API void r_big_divmod(RNumBig *c, RNumBig *d, RNumBig *a, RNumBig *b) {
393 /*
394 Puts a%b in d
395 and a/b in c
396
397 mod(a,b) = a - ((a / b) * b)
398
399 example:
400 mod(8, 3) = 8 - ((8 / 3) * 3) = 2
401 */
402 r_return_if_fail (a);
403 r_return_if_fail (b);
404 r_return_if_fail (c);
405 r_return_if_fail (!r_big_is_zero (b));
406
407 RNumBig *tmp = r_big_new ();
408
409 /* c = (a / b) */
410 r_big_div (c, a, b);
411
412 /* tmp = (c * b) */
413 r_big_mul (tmp, c, b);
414
415 /* d = a - tmp */
416 r_big_sub (d, a, tmp);
417
418 r_big_free (tmp);
419 }
420
r_big_and(RNumBig * c,RNumBig * a,RNumBig * b)421 R_API void r_big_and(RNumBig *c, RNumBig *a, RNumBig *b) {
422 r_return_if_fail (a);
423 r_return_if_fail (b);
424 r_return_if_fail (c);
425 r_return_if_fail (a->sign > 0);
426 r_return_if_fail (b->sign > 0);
427
428 int i;
429 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
430 c->array[i] = (a->array[i] & b->array[i]);
431 }
432 }
433
r_big_or(RNumBig * c,RNumBig * a,RNumBig * b)434 R_API void r_big_or(RNumBig *c, RNumBig *a, RNumBig *b) {
435 r_return_if_fail (a);
436 r_return_if_fail (b);
437 r_return_if_fail (c);
438 r_return_if_fail (a->sign > 0);
439 r_return_if_fail (b->sign > 0);
440
441 int i;
442 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
443 c->array[i] = (a->array[i] | b->array[i]);
444 }
445 }
446
r_big_xor(RNumBig * c,RNumBig * a,RNumBig * b)447 R_API void r_big_xor(RNumBig *c, RNumBig *a, RNumBig *b) {
448 r_return_if_fail (a);
449 r_return_if_fail (b);
450 r_return_if_fail (c);
451 r_return_if_fail (a->sign > 0);
452 r_return_if_fail (b->sign > 0);
453
454 int i;
455 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
456 c->array[i] = (a->array[i] ^ b->array[i]);
457 }
458 }
459
r_big_lshift(RNumBig * b,RNumBig * a,size_t nbits)460 R_API void r_big_lshift(RNumBig *b, RNumBig *a, size_t nbits) {
461 r_return_if_fail (a);
462 r_return_if_fail (b);
463 r_return_if_fail (a->sign > 0);
464 r_return_if_fail (b->sign > 0);
465
466 r_big_assign (b, a);
467 /* Handle shift in multiples of word-size */
468 const int nbits_pr_word = (R_BIG_WORD_SIZE * 8);
469 int nwords = nbits / nbits_pr_word;
470 if (nwords != 0) {
471 _lshift_word (b, nwords);
472 nbits -= (nwords * nbits_pr_word);
473 }
474
475 if (nbits != 0) {
476 int i;
477 for (i = (R_BIG_ARRAY_SIZE - 1); i > 0; i--) {
478 b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * R_BIG_WORD_SIZE) - nbits));
479 }
480 b->array[i] <<= nbits;
481 }
482 }
483
r_big_rshift(RNumBig * b,RNumBig * a,size_t nbits)484 R_API void r_big_rshift(RNumBig *b, RNumBig *a, size_t nbits) {
485 r_return_if_fail (a);
486 r_return_if_fail (b);
487 r_return_if_fail (a->sign > 0);
488 r_return_if_fail (b->sign > 0);
489
490 r_big_assign (b, a);
491 /* Handle shift in multiples of word-size */
492 const int nbits_pr_word = (R_BIG_WORD_SIZE * 8);
493 int nwords = nbits / nbits_pr_word;
494 if (nwords != 0) {
495 _rshift_word (b, nwords);
496 nbits -= (nwords * nbits_pr_word);
497 }
498
499 if (nbits != 0) {
500 int i;
501 for (i = 0; i < (R_BIG_ARRAY_SIZE - 1); i++) {
502 b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * R_BIG_WORD_SIZE) - nbits));
503 }
504 b->array[i] >>= nbits;
505 }
506 }
507
r_big_cmp(RNumBig * a,RNumBig * b)508 R_API int r_big_cmp(RNumBig *a, RNumBig *b) {
509 r_return_val_if_fail (a, 0);
510 r_return_val_if_fail (b, 0);
511
512 if (a->sign != b->sign)
513 return a->sign > 0? 1: -1;
514
515 int i = R_BIG_ARRAY_SIZE;
516 do {
517 i -= 1; /* Decrement first, to start with last array element */
518 if (a->array[i] > b->array[i]) {
519 return 1 * a->sign;
520 }
521 if (a->array[i] < b->array[i]) {
522 return -1 * a->sign;
523 }
524 } while (i != 0);
525
526 return 0;
527 }
528
r_big_is_zero(RNumBig * a)529 R_API int r_big_is_zero(RNumBig *a) {
530 r_return_val_if_fail (a, -1);
531
532 int i;
533 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
534 if (a->array[i]) {
535 return 0;
536 }
537 }
538
539 return 1;
540 }
541
r_big_inc(RNumBig * a)542 R_API void r_big_inc(RNumBig *a) {
543 r_return_if_fail (a);
544 RNumBig *tmp = r_big_new ();
545
546 r_big_from_int (tmp, 1);
547 r_big_add (a, a, tmp);
548
549 r_big_free (tmp);
550 }
551
r_big_dec(RNumBig * a)552 R_API void r_big_dec(RNumBig *a) {
553 r_return_if_fail (a);
554 RNumBig *tmp = r_big_new ();
555
556 r_big_from_int (tmp, 1);
557 r_big_sub (a, a, tmp);
558
559 r_big_free (tmp);
560 }
561
r_big_powm(RNumBig * c,RNumBig * a,RNumBig * b,RNumBig * m)562 R_API void r_big_powm(RNumBig *c, RNumBig *a, RNumBig *b, RNumBig *m) {
563 r_return_if_fail (a);
564 r_return_if_fail (b);
565 r_return_if_fail (c);
566 r_return_if_fail (m);
567
568 RNumBig *bcopy = r_big_new ();
569 RNumBig *acopy = r_big_new ();
570
571 r_big_assign (bcopy, b);
572 r_big_assign (acopy, a);
573 r_big_mod (acopy, acopy, m);
574 r_big_from_int (c, 1);
575
576 while (!r_big_is_zero (bcopy)) {
577 if (r_big_to_int (bcopy) % 2 == 1) {
578 r_big_mul (c, c, acopy);
579 r_big_mod (c, c, m);
580 }
581 _rshift_one_bit (bcopy);
582 r_big_mul (acopy, acopy, acopy);
583 r_big_mod (acopy, acopy, m);
584 }
585
586 r_big_free (bcopy);
587 r_big_free (acopy);
588 }
589
r_big_isqrt(RNumBig * b,RNumBig * a)590 R_API void r_big_isqrt(RNumBig *b, RNumBig *a) {
591 r_return_if_fail (a);
592 r_return_if_fail (b);
593
594 RNumBig *tmp = r_big_new ();
595 RNumBig *low = r_big_new ();
596 RNumBig *high = r_big_new ();
597 RNumBig *mid = r_big_new ();
598
599 r_big_assign (high, a);
600 r_big_rshift (mid, high, 1);
601 r_big_inc (mid);
602
603 while (r_big_cmp (high, low) > 0) {
604 r_big_mul (tmp, mid, mid);
605 if (r_big_cmp (tmp, a) > 0) {
606 r_big_assign (high, mid);
607 r_big_dec (high);
608 } else {
609 r_big_assign (low, mid);
610 }
611 r_big_sub (mid, high, low);
612 _rshift_one_bit (mid);
613 r_big_add (mid, mid, low);
614 r_big_inc (mid);
615 }
616 r_big_assign (b, low);
617
618 r_big_free (tmp);
619 r_big_free (low);
620 r_big_free (high);
621 r_big_free (mid);
622 }
623
624 /* Private / Static functions. */
_rshift_word(RNumBig * a,int nwords)625 static void _rshift_word(RNumBig *a, int nwords) {
626 /* Naive method: */
627 r_return_if_fail (a);
628 r_return_if_fail (nwords >= 0);
629
630 size_t i;
631 if (nwords >= R_BIG_ARRAY_SIZE) {
632 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
633 a->array[i] = 0;
634 }
635 return;
636 }
637
638 for (i = 0; i < R_BIG_ARRAY_SIZE - nwords; i++) {
639 a->array[i] = a->array[i + nwords];
640 }
641 for (; i < R_BIG_ARRAY_SIZE; i++) {
642 a->array[i] = 0;
643 }
644 }
645
_lshift_word(RNumBig * a,int nwords)646 static void _lshift_word(RNumBig *a, int nwords) {
647 r_return_if_fail (a);
648 r_return_if_fail (nwords >= 0);
649
650 int i;
651 /* Shift whole words */
652 for (i = (R_BIG_ARRAY_SIZE - 1); i >= nwords; i--) {
653 a->array[i] = a->array[i - nwords];
654 }
655 /* Zero pad shifted words. */
656 for (; i >= 0; i--) {
657 a->array[i] = 0;
658 }
659 }
660
_lshift_one_bit(RNumBig * a)661 static void _lshift_one_bit(RNumBig *a) {
662 r_return_if_fail (a);
663
664 int i;
665 for (i = (R_BIG_ARRAY_SIZE - 1); i > 0; i--) {
666 a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * R_BIG_WORD_SIZE) - 1));
667 }
668 a->array[0] <<= 1;
669 }
670
_rshift_one_bit(RNumBig * a)671 static void _rshift_one_bit(RNumBig *a) {
672 r_return_if_fail (a);
673
674 int i;
675 for (i = 0; i < (R_BIG_ARRAY_SIZE - 1); i++) {
676 a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * R_BIG_WORD_SIZE) - 1));
677 }
678 a->array[R_BIG_ARRAY_SIZE - 1] >>= 1;
679 }
680
_r_big_zero_out(RNumBig * a)681 static void _r_big_zero_out(RNumBig *a) {
682 r_return_if_fail (a);
683
684 size_t i;
685 for (i = 0; i < R_BIG_ARRAY_SIZE; i++) {
686 a->array[i] = 0;
687 }
688 a->sign = 1; /* hack to avoid -0 */
689 }
690