• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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