1 /*
2 Name: gmp_compat.c
3 Purpose: Provide GMP compatiable routines for imath library
4 Author: David Peixotto
5
6 Copyright (c) 2012 Qualcomm Innovation Center, Inc. All rights reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25 */
26 #include "gmp_compat.h"
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <stdio.h>
32
33 #if defined(_MSC_VER)
34 #include <BaseTsd.h>
35 typedef SSIZE_T ssize_t;
36 #endif
37
38 #ifdef NDEBUG
39 #define CHECK(res) (res)
40 #else
41 #define CHECK(res) assert(((res) == MP_OK) && "expected MP_OK")
42 #endif
43
44 /* *(signed char *)&endian_test will thus either be:
45 * 0b00000001 = 1 on big-endian
46 * 0b11111111 = -1 on little-endian */
47 static const uint16_t endian_test = 0x1FF;
48 #define HOST_ENDIAN (*(signed char *)&endian_test)
49
50 /*************************************************************************
51 *
52 * Functions with direct translations
53 *
54 *************************************************************************/
55 /* gmp: mpq_clear */
GMPQAPI(clear)56 void GMPQAPI(clear)(mp_rat x) {
57 mp_rat_clear(x);
58 }
59
60 /* gmp: mpq_cmp */
GMPQAPI(cmp)61 int GMPQAPI(cmp)(mp_rat op1, mp_rat op2) {
62 return mp_rat_compare(op1, op2);
63 }
64
65 /* gmp: mpq_init */
GMPQAPI(init)66 void GMPQAPI(init)(mp_rat x) {
67 CHECK(mp_rat_init(x));
68 }
69
70 /* gmp: mpq_mul */
GMPQAPI(mul)71 void GMPQAPI(mul)(mp_rat product, mp_rat multiplier, mp_rat multiplicand) {
72 CHECK(mp_rat_mul(multiplier, multiplicand, product));
73 }
74
75 /* gmp: mpq_set*/
GMPQAPI(set)76 void GMPQAPI(set)(mp_rat rop, mp_rat op) {
77 CHECK(mp_rat_copy(op, rop));
78 }
79
80 /* gmp: mpz_abs */
GMPZAPI(abs)81 void GMPZAPI(abs)(mp_int rop, mp_int op) {
82 CHECK(mp_int_abs(op, rop));
83 }
84
85 /* gmp: mpz_add */
GMPZAPI(add)86 void GMPZAPI(add)(mp_int rop, mp_int op1, mp_int op2) {
87 CHECK(mp_int_add(op1, op2, rop));
88 }
89
90 /* gmp: mpz_clear */
GMPZAPI(clear)91 void GMPZAPI(clear)(mp_int x) {
92 mp_int_clear(x);
93 }
94
95 /* gmp: mpz_cmp_si */
GMPZAPI(cmp_si)96 int GMPZAPI(cmp_si)(mp_int op1, long op2) {
97 return mp_int_compare_value(op1, op2);
98 }
99
100 /* gmp: mpz_cmpabs */
GMPZAPI(cmpabs)101 int GMPZAPI(cmpabs)(mp_int op1, mp_int op2) {
102 return mp_int_compare_unsigned(op1, op2);
103 }
104
105 /* gmp: mpz_cmp */
GMPZAPI(cmp)106 int GMPZAPI(cmp)(mp_int op1, mp_int op2) {
107 return mp_int_compare(op1, op2);
108 }
109
110 /* gmp: mpz_init */
GMPZAPI(init)111 void GMPZAPI(init)(mp_int x) {
112 CHECK(mp_int_init(x));
113 }
114
115 /* gmp: mpz_mul */
GMPZAPI(mul)116 void GMPZAPI(mul)(mp_int rop, mp_int op1, mp_int op2) {
117 CHECK(mp_int_mul(op1, op2, rop));
118 }
119
120 /* gmp: mpz_neg */
GMPZAPI(neg)121 void GMPZAPI(neg)(mp_int rop, mp_int op) {
122 CHECK(mp_int_neg(op, rop));
123 }
124
125 /* gmp: mpz_set_si */
GMPZAPI(set_si)126 void GMPZAPI(set_si)(mp_int rop, long op) {
127 CHECK(mp_int_set_value(rop, op));
128 }
129
130 /* gmp: mpz_set */
GMPZAPI(set)131 void GMPZAPI(set)(mp_int rop, mp_int op) {
132 CHECK(mp_int_copy(op, rop));
133 }
134
135 /* gmp: mpz_sub */
GMPZAPI(sub)136 void GMPZAPI(sub)(mp_int rop, mp_int op1, mp_int op2) {
137 CHECK(mp_int_sub(op1, op2, rop));
138 }
139
140 /* gmp: mpz_swap */
GMPZAPI(swap)141 void GMPZAPI(swap)(mp_int rop1, mp_int rop2) {
142 mp_int_swap(rop1, rop2);
143 }
144
145 /* gmp: mpq_sgn */
GMPQAPI(sgn)146 int GMPQAPI(sgn)(mp_rat op) {
147 return mp_rat_compare_zero(op);
148 }
149
150 /* gmp: mpz_sgn */
GMPZAPI(sgn)151 int GMPZAPI(sgn)(mp_int op) {
152 return mp_int_compare_zero(op);
153 }
154
155 /* gmp: mpq_set_ui */
GMPQAPI(set_ui)156 void GMPQAPI(set_ui)(mp_rat rop, unsigned long op1, unsigned long op2) {
157 CHECK(mp_rat_set_uvalue(rop, op1, op2));
158 }
159
160 /* gmp: mpz_set_ui */
GMPZAPI(set_ui)161 void GMPZAPI(set_ui)(mp_int rop, unsigned long op) {
162 CHECK(mp_int_set_uvalue(rop, op));
163 }
164
165 /* gmp: mpq_den_ref */
GMPQAPI(denref)166 mp_int GMPQAPI(denref)(mp_rat op) {
167 return mp_rat_denom_ref(op);
168 }
169
170 /* gmp: mpq_num_ref */
GMPQAPI(numref)171 mp_int GMPQAPI(numref)(mp_rat op) {
172 return mp_rat_numer_ref(op);
173 }
174
175 /* gmp: mpq_canonicalize */
GMPQAPI(canonicalize)176 void GMPQAPI(canonicalize)(mp_rat op) {
177 CHECK(mp_rat_reduce(op));
178 }
179
180 /*************************************************************************
181 *
182 * Functions that can be implemented as a combination of imath functions
183 *
184 *************************************************************************/
185 /* gmp: mpz_addmul */
186 /* gmp: rop = rop + (op1 * op2) */
GMPZAPI(addmul)187 void GMPZAPI(addmul)(mp_int rop, mp_int op1, mp_int op2) {
188 mpz_t tempz;
189 mp_int temp = &tempz;
190 mp_int_init(temp);
191
192 CHECK(mp_int_mul(op1, op2, temp));
193 CHECK(mp_int_add(rop, temp, rop));
194 mp_int_clear(temp);
195 }
196
197 /* gmp: mpz_divexact */
198 /* gmp: only produces correct results when d divides n */
GMPZAPI(divexact)199 void GMPZAPI(divexact)(mp_int q, mp_int n, mp_int d) {
200 CHECK(mp_int_div(n, d, q, NULL));
201 }
202
203 /* gmp: mpz_divisible_p */
204 /* gmp: return 1 if d divides n, 0 otherwise */
205 /* gmp: 0 is considered to divide only 0 */
GMPZAPI(divisible_p)206 int GMPZAPI(divisible_p)(mp_int n, mp_int d) {
207 /* variables to hold remainder */
208 mpz_t rz;
209 mp_int r = &rz;
210 int r_is_zero;
211
212 /* check for d = 0 */
213 int n_is_zero = mp_int_compare_zero(n) == 0;
214 int d_is_zero = mp_int_compare_zero(d) == 0;
215 if (d_is_zero)
216 return n_is_zero;
217
218 /* return true if remainder is 0 */
219 CHECK(mp_int_init(r));
220 CHECK(mp_int_div(n, d, NULL, r));
221 r_is_zero = mp_int_compare_zero(r) == 0;
222 mp_int_clear(r);
223
224 return r_is_zero;
225 }
226
227 /* gmp: mpz_submul */
228 /* gmp: rop = rop - (op1 * op2) */
GMPZAPI(submul)229 void GMPZAPI(submul)(mp_int rop, mp_int op1, mp_int op2) {
230 mpz_t tempz;
231 mp_int temp = &tempz;
232 mp_int_init(temp);
233
234 CHECK(mp_int_mul(op1, op2, temp));
235 CHECK(mp_int_sub(rop, temp, rop));
236
237 mp_int_clear(temp);
238 }
239
240 /* gmp: mpz_add_ui */
GMPZAPI(add_ui)241 void GMPZAPI(add_ui)(mp_int rop, mp_int op1, unsigned long op2) {
242 mpz_t tempz;
243 mp_int temp = &tempz;
244 CHECK(mp_int_init_uvalue(temp, op2));
245
246 CHECK(mp_int_add(op1, temp, rop));
247
248 mp_int_clear(temp);
249 }
250
251 /* gmp: mpz_divexact_ui */
252 /* gmp: only produces correct results when d divides n */
GMPZAPI(divexact_ui)253 void GMPZAPI(divexact_ui)(mp_int q, mp_int n, unsigned long d) {
254 mpz_t tempz;
255 mp_int temp = &tempz;
256 CHECK(mp_int_init_uvalue(temp, d));
257
258 CHECK(mp_int_div(n, temp, q, NULL));
259
260 mp_int_clear(temp);
261 }
262
263 /* gmp: mpz_mul_ui */
GMPZAPI(mul_ui)264 void GMPZAPI(mul_ui)(mp_int rop, mp_int op1, unsigned long op2) {
265 mpz_t tempz;
266 mp_int temp = &tempz;
267 CHECK(mp_int_init_uvalue(temp, op2));
268
269 CHECK(mp_int_mul(op1, temp, rop));
270
271 mp_int_clear(temp);
272 }
273
274 /* gmp: mpz_pow_ui */
275 /* gmp: 0^0 = 1 */
GMPZAPI(pow_ui)276 void GMPZAPI(pow_ui)(mp_int rop, mp_int base, unsigned long exp) {
277 mpz_t tempz;
278 mp_int temp = &tempz;
279
280 /* check for 0^0 */
281 if (exp == 0 && mp_int_compare_zero(base) == 0) {
282 CHECK(mp_int_set_value(rop, 1));
283 return;
284 }
285
286 /* rop = base^exp */
287 CHECK(mp_int_init_uvalue(temp, exp));
288 CHECK(mp_int_expt_full(base, temp, rop));
289 mp_int_clear(temp);
290 }
291
292 /* gmp: mpz_sub_ui */
GMPZAPI(sub_ui)293 void GMPZAPI(sub_ui)(mp_int rop, mp_int op1, unsigned long op2) {
294 mpz_t tempz;
295 mp_int temp = &tempz;
296 CHECK(mp_int_init_uvalue(temp, op2));
297
298 CHECK(mp_int_sub(op1, temp, rop));
299
300 mp_int_clear(temp);
301 }
302
303 /*************************************************************************
304 *
305 * Functions with different behavior in corner cases
306 *
307 *************************************************************************/
308
309 /* gmp: mpz_gcd */
GMPZAPI(gcd)310 void GMPZAPI(gcd)(mp_int rop, mp_int op1, mp_int op2) {
311 int op1_is_zero = mp_int_compare_zero(op1) == 0;
312 int op2_is_zero = mp_int_compare_zero(op2) == 0;
313
314 if (op1_is_zero && op2_is_zero) {
315 mp_int_zero(rop);
316 return;
317 }
318
319 CHECK(mp_int_gcd(op1, op2, rop));
320 }
321
322 /* gmp: mpz_get_str */
GMPZAPI(get_str)323 char* GMPZAPI(get_str)(char *str, int radix, mp_int op) {
324 int i, r, len;
325
326 /* Support negative radix like gmp */
327 r = radix;
328 if (r < 0)
329 r = -r;
330
331 /* Compute the length of the string needed to hold the int */
332 len = mp_int_string_len(op, r);
333 if (str == NULL) {
334 str = malloc(len);
335 }
336
337 /* Convert to string using imath function */
338 CHECK(mp_int_to_string(op, r, str, len));
339
340 /* Change case to match gmp */
341 for (i = 0; i < len - 1; i++)
342 if (radix < 0)
343 str[i] = toupper(str[i]);
344 else
345 str[i] = tolower(str[i]);
346 return str;
347 }
348
349 /* gmp: mpq_get_str */
GMPQAPI(get_str)350 char* GMPQAPI(get_str)(char *str, int radix, mp_rat op) {
351 int i, r, len;
352
353 /* Only print numerator if it is a whole number */
354 if (mp_int_compare_value(mp_rat_denom_ref(op), 1) == 0)
355 return GMPZAPI(get_str)(str, radix, mp_rat_numer_ref(op));
356
357 /* Support negative radix like gmp */
358 r = radix;
359 if (r < 0)
360 r = -r;
361
362 /* Compute the length of the string needed to hold the int */
363 len = mp_rat_string_len(op, r);
364 if (str == NULL) {
365 str = malloc(len);
366 }
367
368 /* Convert to string using imath function */
369 CHECK(mp_rat_to_string(op, r, str, len));
370
371 /* Change case to match gmp */
372 for (i = 0; i < len; i++)
373 if (radix < 0)
374 str[i] = toupper(str[i]);
375 else
376 str[i] = tolower(str[i]);
377
378 return str;
379 }
380
381 /* gmp: mpz_set_str */
GMPZAPI(set_str)382 int GMPZAPI(set_str)(mp_int rop, char *str, int base) {
383 mp_result res = mp_int_read_string(rop, base, str);
384 return ((res == MP_OK) ? 0 : -1);
385 }
386
387 /* gmp: mpq_set_str */
GMPQAPI(set_str)388 int GMPQAPI(set_str)(mp_rat rop, char *s, int base) {
389 char *slash;
390 char *str;
391 mp_result resN;
392 mp_result resD;
393 int res = 0;
394
395 /* Copy string to temporary storage so we can modify it below */
396 str = malloc(strlen(s)+1);
397 strcpy(str, s);
398
399 /* Properly format the string as an int by terminating at the / */
400 slash = strchr(str, '/');
401 if (slash)
402 *slash = '\0';
403
404 /* Parse numerator */
405 resN = mp_int_read_string(mp_rat_numer_ref(rop), base, str);
406
407 /* Parse denomenator if given or set to 1 if not */
408 if (slash)
409 resD = mp_int_read_string(mp_rat_denom_ref(rop), base, slash+1);
410 else
411 resD = mp_int_set_uvalue(mp_rat_denom_ref(rop), 1);
412
413 /* Return failure if either parse failed */
414 if (resN != MP_OK || resD != MP_OK)
415 res = -1;
416
417 free(str);
418 return res;
419 }
420
get_long_bits(mp_int op)421 static unsigned long get_long_bits(mp_int op) {
422 /* Deal with integer that does not fit into unsigned long. We want to grab
423 * the least significant digits that will fit into the long. Read the digits
424 * into the long starting at the most significant digit that fits into a
425 * long. The long is shifted over by MP_DIGIT_BIT before each digit is added.
426 * The shift is decomposed into two steps to follow the patten used in the
427 * rest of the imath library. The two step shift is used to accomedate
428 * architectures that don't deal well with 32-bit shifts. */
429 mp_size num_digits_in_long = sizeof(unsigned long) / sizeof(mp_digit);
430 mp_digit *digits = MP_DIGITS(op);
431 unsigned long out = 0;
432 int i;
433
434 for (i = num_digits_in_long - 1; i >= 0; i--) {
435 out <<= (MP_DIGIT_BIT/2);
436 out <<= (MP_DIGIT_BIT/2);
437 out |= digits[i];
438 }
439
440 return out;
441 }
442
443 /* gmp: mpz_get_ui */
GMPZAPI(get_ui)444 unsigned long GMPZAPI(get_ui)(mp_int op) {
445 unsigned long out;
446
447 /* Try a standard conversion that fits into an unsigned long */
448 mp_result res = mp_int_to_uint(op, &out);
449 if (res == MP_OK)
450 return out;
451
452 /* Abort the try if we don't have a range error in the conversion.
453 * The range error indicates that the value cannot fit into a long. */
454 CHECK(res == MP_RANGE ? MP_OK : MP_RANGE);
455 if (res != MP_RANGE)
456 return 0;
457
458 return get_long_bits(op);
459 }
460
461 /* gmp: mpz_get_si */
GMPZAPI(get_si)462 long GMPZAPI(get_si)(mp_int op) {
463 long out;
464 unsigned long uout;
465 int long_msb;
466
467 /* Try a standard conversion that fits into a long */
468 mp_result res = mp_int_to_int(op, &out);
469 if (res == MP_OK)
470 return out;
471
472 /* Abort the try if we don't have a range error in the conversion.
473 * The range error indicates that the value cannot fit into a long. */
474 CHECK(res == MP_RANGE ? MP_OK : MP_RANGE);
475 if (res != MP_RANGE)
476 return 0;
477
478 /* get least significant bits into an unsigned long */
479 uout = get_long_bits(op);
480
481 /* clear the top bit */
482 long_msb = (sizeof(unsigned long) * 8) - 1;
483 uout &= (~(1UL << long_msb));
484
485 /* convert to negative if needed based on sign of op */
486 if (MP_SIGN(op) == MP_NEG)
487 uout = 0 - uout;
488
489 out = (long) uout;
490 return out;
491 }
492
493 /* gmp: mpz_lcm */
GMPZAPI(lcm)494 void GMPZAPI(lcm)(mp_int rop, mp_int op1, mp_int op2) {
495 int op1_is_zero = mp_int_compare_zero(op1) == 0;
496 int op2_is_zero = mp_int_compare_zero(op2) == 0;
497
498 if (op1_is_zero || op2_is_zero) {
499 mp_int_zero(rop);
500 return;
501 }
502
503 CHECK(mp_int_lcm(op1, op2, rop));
504 CHECK(mp_int_abs(rop, rop));
505 }
506
507 /* gmp: mpz_mul_2exp */
508 /* gmp: allow big values for op2 when op1 == 0 */
GMPZAPI(mul_2exp)509 void GMPZAPI(mul_2exp)(mp_int rop, mp_int op1, unsigned long op2) {
510 if (mp_int_compare_zero(op1) == 0)
511 mp_int_zero(rop);
512 else
513 CHECK(mp_int_mul_pow2(op1, op2, rop));
514 }
515
516 /*************************************************************************
517 *
518 * Functions needing expanded functionality
519 *
520 *************************************************************************/
521 /* [Note]Overview of division implementation
522
523 All division operations (N / D) compute q and r such that
524
525 N = q * D + r, with 0 <= abs(r) < abs(d)
526
527 The q and r values are not uniquely specified by N and D. To specify which q
528 and r values should be used, GMP implements three different rounding modes
529 for integer division:
530
531 ceiling - round q twords +infinity, r has opposite sign as d
532 floor - round q twords -infinity, r has same sign as d
533 truncate - round q twords zero, r has same sign as n
534
535 The imath library only supports truncate as a rounding mode. We need to
536 implement the other rounding modes in terms of truncating division. We first
537 perform the division in trucate mode and then adjust q accordingly. Once we
538 know q, we can easily compute the correct r according the the formula above
539 by computing:
540
541 r = N - q * D
542
543 The main task is to compute q. We can compute the correct q from a trucated
544 version as follows.
545
546 For ceiling rounding mode, if q is less than 0 then the truncated rounding
547 mode is the same as the ceiling rounding mode. If q is greater than zero
548 then we need to round q up by one because the truncated version was rounded
549 down to zero. If q equals zero then check to see if the result of the
550 divison is positive. A positive result needs to increment q to one.
551
552 For floor rounding mode, if q is greater than 0 then the trucated rounding
553 mode is the same as the floor rounding mode. If q is less than zero then we
554 need to round q down by one because the trucated mode rounded q up by one
555 twords zero. If q is zero then we need to check to see if the result of the
556 division is negative. A negative result needs to decrement q to negative
557 one.
558 */
559
560 /* gmp: mpz_cdiv_q */
GMPZAPI(cdiv_q)561 void GMPZAPI(cdiv_q)(mp_int q, mp_int n, mp_int d) {
562 mpz_t rz;
563 mp_int r = &rz;
564 int qsign, rsign, nsign, dsign;
565 CHECK(mp_int_init(r));
566
567 /* save signs before division because q can alias with n or d */
568 nsign = mp_int_compare_zero(n);
569 dsign = mp_int_compare_zero(d);
570
571 /* truncating division */
572 CHECK(mp_int_div(n, d, q, r));
573
574 /* see: [Note]Overview of division implementation */
575 qsign = mp_int_compare_zero(q);
576 rsign = mp_int_compare_zero(r);
577 if (qsign > 0) { /* q > 0 */
578 if (rsign != 0) { /* r != 0 */
579 CHECK(mp_int_add_value(q, 1, q));
580 }
581 }
582 else if (qsign == 0) { /* q == 0 */
583 if (rsign != 0) { /* r != 0 */
584 if ((nsign > 0 && dsign > 0) || (nsign < 0 && dsign < 0)) {
585 CHECK(mp_int_set_value(q, 1));
586 }
587 }
588 }
589 mp_int_clear(r);
590 }
591
592 /* gmp: mpz_fdiv_q */
GMPZAPI(fdiv_q)593 void GMPZAPI(fdiv_q)(mp_int q, mp_int n, mp_int d) {
594 mpz_t rz;
595 mp_int r = &rz;
596 int qsign, rsign, nsign, dsign;
597 CHECK(mp_int_init(r));
598
599 /* save signs before division because q can alias with n or d */
600 nsign = mp_int_compare_zero(n);
601 dsign = mp_int_compare_zero(d);
602
603 /* truncating division */
604 CHECK(mp_int_div(n, d, q, r));
605
606 /* see: [Note]Overview of division implementation */
607 qsign = mp_int_compare_zero(q);
608 rsign = mp_int_compare_zero(r);
609 if (qsign < 0) { /* q < 0 */
610 if (rsign != 0) { /* r != 0 */
611 CHECK(mp_int_sub_value(q, 1, q));
612 }
613 }
614 else if (qsign == 0) { /* q == 0 */
615 if (rsign != 0) { /* r != 0 */
616 if ((nsign < 0 && dsign > 0) || (nsign > 0 && dsign < 0)) {
617 CHECK(mp_int_set_value(q, -1));
618 }
619 }
620 }
621 mp_int_clear(r);
622 }
623
624 /* gmp: mpz_fdiv_r */
GMPZAPI(fdiv_r)625 void GMPZAPI(fdiv_r)(mp_int r, mp_int n, mp_int d) {
626 mpz_t qz;
627 mpz_t tempz;
628 mpz_t orig_dz;
629 mpz_t orig_nz;
630 mp_int q = &qz;
631 mp_int temp = &tempz;
632 mp_int orig_d = &orig_dz;
633 mp_int orig_n = &orig_nz;
634 CHECK(mp_int_init(q));
635 CHECK(mp_int_init(temp));
636 /* Make a copy of n in case n and d in case they overlap with q */
637 CHECK(mp_int_init_copy(orig_d, d));
638 CHECK(mp_int_init_copy(orig_n, n));
639
640 /* floor division */
641 GMPZAPI(fdiv_q)(q, n, d);
642
643 /* see: [Note]Overview of division implementation */
644 /* n = q * d + r ==> r = n - q * d */
645 mp_int_mul(q, orig_d, temp);
646 mp_int_sub(orig_n, temp, r);
647
648 mp_int_clear(q);
649 mp_int_clear(temp);
650 mp_int_clear(orig_d);
651 mp_int_clear(orig_n);
652 }
653
654 /* gmp: mpz_tdiv_q */
GMPZAPI(tdiv_q)655 void GMPZAPI(tdiv_q)(mp_int q, mp_int n, mp_int d) {
656 /* truncating division*/
657 CHECK(mp_int_div(n, d, q, NULL));
658 }
659
660 /* gmp: mpz_fdiv_q_ui */
GMPZAPI(fdiv_q_ui)661 unsigned long GMPZAPI(fdiv_q_ui)(mp_int q, mp_int n, unsigned long d) {
662 mpz_t tempz;
663 mp_int temp = &tempz;
664 mpz_t rz;
665 mp_int r = &rz;
666 mpz_t orig_nz;
667 mp_int orig_n = &orig_nz;
668 unsigned long rl;
669 CHECK(mp_int_init_uvalue(temp, d));
670 CHECK(mp_int_init(r));
671 /* Make a copy of n in case n and q overlap */
672 CHECK(mp_int_init_copy(orig_n, n));
673
674 /* use floor division mode to compute q and r */
675 GMPZAPI(fdiv_q)(q, n, temp);
676 GMPZAPI(fdiv_r)(r, orig_n, temp);
677 CHECK(mp_int_to_uint(r, &rl));
678
679 mp_int_clear(temp);
680 mp_int_clear(r);
681 mp_int_clear(orig_n);
682
683 return rl;
684 }
685
686 /* gmp: mpz_export */
GMPZAPI(export)687 void* GMPZAPI(export)(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, mp_int op) {
688 int i, j;
689 int num_used_bytes;
690 size_t num_words, num_missing_bytes;
691 ssize_t word_offset;
692 unsigned char* dst;
693 mp_digit* src;
694 int src_bits;
695
696 /* We do not have a complete implementation. Assert to ensure our
697 * restrictions are in place. */
698 assert(nails == 0 && "Do not support non-full words");
699 assert(endian == 1 || endian == 0 || endian == -1);
700 assert(order == 1 || order == -1);
701
702 /* Test for zero */
703 if (mp_int_compare_zero(op) == 0) {
704 if (countp)
705 *countp = 0;
706 return rop;
707 }
708
709 /* Calculate how many words we need */
710 num_used_bytes = mp_int_unsigned_len(op);
711 num_words = (num_used_bytes + (size-1)) / size; /* ceil division */
712 assert(num_used_bytes > 0);
713
714 /* Check to see if we will have missing bytes in the last word.
715
716 Missing bytes can only occur when the size of words we output is
717 greater than the size of words used internally by imath. The number of
718 missing bytes is the number of bytes needed to fill out the last word. If
719 this number is greater than the size of a single mp_digit, then we need to
720 pad the word with extra zeros. Otherwise, the missing bytes can be filled
721 directly from the zeros in the last digit in the number.
722 */
723 num_missing_bytes = (size * num_words) - num_used_bytes;
724 assert(num_missing_bytes < size);
725
726 /* Allocate space for the result if needed */
727 if (rop == NULL) {
728 rop = malloc(num_words * size);
729 }
730
731 if (endian == 0) {
732 endian = HOST_ENDIAN;
733 }
734
735 /* Initialize dst and src pointers */
736 dst = (unsigned char *) rop + (order >= 0 ? (num_words-1) * size : 0) + (endian >= 0 ? size-1 : 0);
737 src = MP_DIGITS(op);
738 src_bits = MP_DIGIT_BIT;
739
740 word_offset = (endian >= 0 ? size : -size) + (order < 0 ? size : -size);
741
742 for (i = 0; i < num_words; i++) {
743 for (j = 0; j < size && i * size + j < num_used_bytes; j++) {
744 if (src_bits == 0) {
745 ++src;
746 src_bits = MP_DIGIT_BIT;
747 }
748 *dst = (*src >> (MP_DIGIT_BIT - src_bits)) & 0xFF;
749 src_bits -= 8;
750 dst -= endian;
751 }
752 for (; j < size; j++) {
753 *dst = 0;
754 dst -= endian;
755 }
756 dst += word_offset;
757 }
758
759 if (countp)
760 *countp = num_words;
761 return rop;
762 }
763
764 /* gmp: mpz_import */
GMPZAPI(import)765 void GMPZAPI(import)(mp_int rop, size_t count, int order, size_t size, int endian, size_t nails, const void* op) {
766 mpz_t tmpz;
767 mp_int tmp = &tmpz;
768 size_t total_size;
769 size_t num_digits;
770 ssize_t word_offset;
771 const unsigned char *src;
772 mp_digit *dst;
773 int dst_bits;
774 int i, j;
775 if (count == 0 || op == NULL)
776 return;
777
778 /* We do not have a complete implementation. Assert to ensure our
779 * restrictions are in place. */
780 assert(nails == 0 && "Do not support non-full words");
781 assert(endian == 1 || endian == 0 || endian == -1);
782 assert(order == 1 || order == -1);
783
784 if (endian == 0) {
785 endian = HOST_ENDIAN;
786 }
787
788 /* Compute number of needed digits by ceil division */
789 total_size = count * size;
790 num_digits = (total_size + sizeof(mp_digit) - 1) / sizeof(mp_digit);
791
792 /* Init temporary */
793 mp_int_init_size(tmp, num_digits);
794 for (i = 0; i < num_digits; i++)
795 tmp->digits[i] = 0;
796
797 /* Copy bytes */
798 src = (const unsigned char *) op + (order >= 0 ? (count-1) * size : 0) + (endian >= 0 ? size-1 : 0);
799 dst = MP_DIGITS(tmp);
800 dst_bits = 0;
801
802 word_offset = (endian >= 0 ? size : -size) + (order < 0 ? size : -size);
803
804 for (i = 0; i < count; i++) {
805 for (j = 0; j < size; j++) {
806 if (dst_bits == MP_DIGIT_BIT) {
807 ++dst;
808 dst_bits = 0;
809 }
810 *dst |= ((mp_digit)*src) << dst_bits;
811 dst_bits += 8;
812 src -= endian;
813 }
814 src += word_offset;
815 }
816
817 MP_USED(tmp) = num_digits;
818
819 /* Remove leading zeros from number */
820 {
821 mp_size uz_ = MP_USED(tmp);
822 mp_digit *dz_ = MP_DIGITS(tmp) + uz_ -1;
823 while (uz_ > 1 && (*dz_-- == 0))
824 --uz_;
825 MP_USED(tmp) = uz_;
826 }
827
828 /* Copy to destination */
829 mp_int_copy(tmp, rop);
830 mp_int_clear(tmp);
831 }
832
833 /* gmp: mpz_sizeinbase */
GMPZAPI(sizeinbase)834 size_t GMPZAPI(sizeinbase)(mp_int op, int base) {
835 mp_result res;
836 size_t size;
837
838 /* If op == 0, return 1 */
839 if (mp_int_compare_zero(op) == 0)
840 return 1;
841
842 /* Compute string length in base */
843 res = mp_int_string_len(op, base);
844 CHECK((res > 0) == MP_OK);
845
846 /* Now adjust the final size by getting rid of string artifacts */
847 size = res;
848
849 /* subtract one for the null terminator */
850 size -= 1;
851
852 /* subtract one for the negative sign */
853 if (mp_int_compare_zero(op) < 0)
854 size -= 1;
855
856 return size;
857 }
858