OpenScop  0.9.0
int.c
Go to the documentation of this file.
1 
2  /*+-----------------------------------------------------------------**
3  ** OpenScop Library **
4  **-----------------------------------------------------------------**
5  ** int.c **
6  **-----------------------------------------------------------------**
7  ** First version: 18/07/2011 **
8  **-----------------------------------------------------------------**
9 
10 
11  *****************************************************************************
12  * OpenScop: Structures and formats for polyhedral tools to talk together *
13  *****************************************************************************
14  * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15  * / / / // // // // / / / // // / / // / /|,_, *
16  * / / / // // // // / / / // // / / // / / / /\ *
17  * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18  * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19  * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20  * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21  * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22  * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23  * | I | | | | e | | | | | | | | | | | | | \ \ \ *
24  * | T | | | | | | | | | | | | | | | | | \ \ \ *
25  * | E | | | | | | | | | | | | | | | | | \ \ \ *
26  * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27  * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28  * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
29  * *
30  * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
31  * *
32  * (3-clause BSD license) *
33  * Redistribution and use in source and binary forms, with or without *
34  * modification, are permitted provided that the following conditions *
35  * are met: *
36  * *
37  * 1. Redistributions of source code must retain the above copyright notice, *
38  * this list of conditions and the following disclaimer. *
39  * 2. Redistributions in binary form must reproduce the above copyright *
40  * notice, this list of conditions and the following disclaimer in the *
41  * documentation and/or other materials provided with the distribution. *
42  * 3. The name of the author may not be used to endorse or promote products *
43  * derived from this software without specific prior written permission. *
44  * *
45  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
55  * *
56  * OpenScop Library, a library to manipulate OpenScop formats and data *
57  * structures. Written by: *
58  * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59  * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
60  * *
61  *****************************************************************************/
62 
63 #include <stdlib.h>
64 #include <stdio.h>
65 #include <limits.h>
66 
67 #ifdef OSL_GMP_IS_HERE
68 # include <gmp.h>
69 #endif
70 
71 #include <osl/macros.h>
72 #include <osl/int.h>
73 
74 
75 /*+***************************************************************************
76  * Basic Functions *
77  *****************************************************************************/
78 
79 
90 int osl_int_is_precision_supported(int precision) {
91  switch (precision) {
92  case OSL_PRECISION_SP:
93  return 1;
94  case OSL_PRECISION_DP:
95  return 1;
96 #ifdef OSL_GMP_IS_HERE
97  case OSL_PRECISION_MP:
98  return 1;
99 #endif
100  }
101 
102  return 0;
103 }
104 
105 
113 void osl_int_dump_precision(FILE * file, int precision) {
114  switch (precision) {
115  case OSL_PRECISION_SP:
116  fprintf(file, "32 bits");
117  break;
118  case OSL_PRECISION_DP:
119  fprintf(file, "64 bits");
120  break;
121 #ifdef OSL_GMP_IS_HERE
122  case OSL_PRECISION_MP:
123  fprintf(file, "GMP");
124  break;
125 #endif
126  default:
127  fprintf(file, "unknown precision %d", precision);
128  }
129 }
130 
131 
137 void osl_int_init(int precision, osl_int_const_p variable) {
138  switch (precision) {
139  case OSL_PRECISION_SP:
140  variable->sp = 0;
141  break;
142 
143  case OSL_PRECISION_DP:
144  variable->dp = 0;
145  break;
146 
147 #ifdef OSL_GMP_IS_HERE
148  case OSL_PRECISION_MP:
149  OSL_malloc(variable->mp, void*, sizeof(mpz_t));
150  mpz_init(*variable->mp);
151  break;
152 #endif
153 
154  default:
155  OSL_error("unknown precision");
156  }
157 }
158 
159 
164 osl_int_p osl_int_malloc(int precision) {
165  osl_int_p variable;
166 
167  OSL_malloc(variable, osl_int_p, sizeof(osl_int_t));
168  osl_int_init(precision, variable);
169  return variable;
170 }
171 
172 
179 void osl_int_assign(int precision,
180  osl_int_const_p variable, osl_const_int_t value) {
181  switch (precision) {
182  case OSL_PRECISION_SP:
183  variable->sp = value.sp;
184  break;
185 
186  case OSL_PRECISION_DP:
187  variable->dp = value.dp;
188  break;
189 
190 #ifdef OSL_GMP_IS_HERE
191  case OSL_PRECISION_MP:
192  mpz_set(*variable->mp, *value.mp);
193  break;
194 #endif
195 
196  default:
197  OSL_error("unknown precision");
198  }
199 }
200 
201 
208 void osl_int_set_si(int precision, osl_int_const_p variable, int i) {
209  switch (precision) {
210  case OSL_PRECISION_SP:
211  variable->sp = (long int)i;
212  break;
213 
214  case OSL_PRECISION_DP:
215  variable->dp = (long long int)i;
216  break;
217 
218 #ifdef OSL_GMP_IS_HERE
219  case OSL_PRECISION_MP:
220  mpz_set_si(*variable->mp, i);
221  break;
222 #endif
223 
224  default:
225  OSL_error("unknown precision");
226  }
227 }
228 
229 
236 int osl_int_get_si(int precision, osl_const_int_t value) {
237  switch (precision) {
238  case OSL_PRECISION_SP:
239  #ifndef NDEBUG
240  if (value.sp > (long int)(INT_MAX))
241  OSL_overflow("osl_int_get_si overflow");
242  if (value.sp < (long int)(INT_MIN))
243  OSL_overflow("osl_int_get_si overflow");
244  #endif
245  return (int)value.sp;
246 
247  case OSL_PRECISION_DP:
248  #ifndef NDEBUG
249  if (value.dp > (long long int)(INT_MAX))
250  OSL_overflow("osl_int_get_si overflow");
251  if (value.dp < (long long int)(INT_MIN))
252  OSL_overflow("osl_int_get_si overflow");
253  #endif
254  return (int)value.dp;
255 
256 #ifdef OSL_GMP_IS_HERE
257  case OSL_PRECISION_MP:
258  #ifndef NDEBUG
259  if (mpz_fits_sint_p(*value.mp) == 0)
260  OSL_overflow("osl_int_get_si overflow");
261  #endif
262  return mpz_get_si(*value.mp);
263 #endif
264 
265  default:
266  OSL_error("unknown precision");
267  }
268 }
269 
270 
277 double osl_int_get_d(int precision, osl_const_int_t i) {
278  switch (precision) {
279  case OSL_PRECISION_SP:
280  return (double)i.sp;
281 
282  case OSL_PRECISION_DP:
283  return (double)i.dp;
284 
285 #ifdef OSL_GMP_IS_HERE
286  case OSL_PRECISION_MP:
287  return mpz_get_d(*i.mp);
288 #endif
289 
290  default:
291  OSL_error("unknown precision");
292  }
293 }
294 
295 
302 void osl_int_init_set(int precision, osl_int_const_p variable, osl_const_int_t i) {
303  osl_int_init(precision, variable);
304  osl_int_assign(precision, variable, i);
305 }
306 
307 
314 void osl_int_init_set_si(int precision, osl_int_const_p variable, int i) {
315  switch (precision) {
316  case OSL_PRECISION_SP:
317  variable->sp = (long int)i;
318  break;
319 
320  case OSL_PRECISION_DP:
321  variable->dp = (long long int)i;
322  break;
323 
324 #ifdef OSL_GMP_IS_HERE
325  case OSL_PRECISION_MP:
326  OSL_malloc(variable->mp, void*, sizeof(mpz_t));
327  mpz_init_set_si(*variable->mp, i);
328  break;
329 #endif
330 
331  default:
332  OSL_error("unknown precision");
333  }
334 }
335 
336 
343 void osl_int_swap(int precision, osl_int_const_p var1, osl_int_const_p var2) {
344  switch (precision) {
345  case OSL_PRECISION_SP: {
346  long int temp = var1->sp;
347  var1->sp = var2->sp;
348  var2->sp = temp;
349  break;
350  }
351 
352  case OSL_PRECISION_DP: {
353  long long int temp = var1->dp;
354  var1->dp = var2->dp;
355  var2->dp = temp;
356  break;
357  }
358 
359 #ifdef OSL_GMP_IS_HERE
360  case OSL_PRECISION_MP: {
361  mpz_t temp;
362  mpz_init(temp);
363  mpz_set(temp, *var1->mp);
364  mpz_set(*var1->mp, *var2->mp);
365  mpz_set(*var2->mp, temp);
366  mpz_clear(temp);
367  break;
368  }
369 #endif
370 
371  default:
372  OSL_error("unknown precision");
373  }
374 }
375 
376 
382 void osl_int_clear(int precision, osl_int_const_p variable) {
383  switch (precision) {
384  case OSL_PRECISION_SP:
385  variable->sp = 0;
386  break;
387 
388  case OSL_PRECISION_DP:
389  variable->dp = 0;
390  break;
391 
392 #ifdef OSL_GMP_IS_HERE
393  case OSL_PRECISION_MP:
394  mpz_clear(*variable->mp);
395  free(variable->mp);
396  break;
397 #endif
398 
399  default:
400  OSL_error("unknown precision");
401  }
402 }
403 
404 
410 void osl_int_free(int precision, osl_int_const_p variable) {
411  osl_int_clear(precision, variable);
412  free(variable);
413 }
414 
415 
423 void osl_int_print(FILE * file, int precision, osl_const_int_t value) {
424  char string[OSL_MAX_STRING];
425 
426  osl_int_sprint(string, precision, value);
427  fprintf(file, "%s", string);
428 }
429 
430 
439 void osl_int_sprint(char * string, int precision, osl_const_int_t value) {
440  switch (precision) {
441  case OSL_PRECISION_SP:
442  sprintf(string, OSL_FMT_SP, value.sp);
443  break;
444 
445  case OSL_PRECISION_DP:
446  sprintf(string, OSL_FMT_DP, value.dp);
447  break;
448 
449 #ifdef OSL_GMP_IS_HERE
450  case OSL_PRECISION_MP: {
451  char * str;
452  str = mpz_get_str(0, 10, *value.mp); //TODO: 10 -> #define
453  sprintf(string, OSL_FMT_MP, str);
454  free(str);
455  break;
456  }
457 #endif
458 
459  default:
460  OSL_error("unknown precision");
461  }
462 }
463 
464 
471 void osl_int_sprint_txt(char * string, int precision, osl_const_int_t value) {
472  switch (precision) {
473  case OSL_PRECISION_SP:
474  sprintf(string, OSL_FMT_TXT_SP, value.sp);
475  break;
476 
477  case OSL_PRECISION_DP:
478  sprintf(string, OSL_FMT_TXT_DP, value.dp);
479  break;
480 
481 #ifdef OSL_GMP_IS_HERE
482  case OSL_PRECISION_MP: {
483  char * str;
484  str = mpz_get_str(0, 10, *value.mp); //TODO: 10 -> #define
485  sprintf(string, OSL_FMT_TXT_MP, str);
486  free(str);
487  break;
488  }
489 #endif
490 
491  default:
492  OSL_error("unknown precision");
493  }
494 }
495 
496 
504 int osl_int_sscanf(char* string, int precision, osl_int_const_p i) {
505  int nb_read = 0;
506 
507  switch (precision) {
508  case OSL_PRECISION_SP:
509  nb_read = sscanf(string, OSL_FMT_TXT_SP, &(i->sp));
510  break;
511 
512  case OSL_PRECISION_DP:
513  nb_read = sscanf(string, OSL_FMT_TXT_DP, &(i->dp));
514  break;
515 
516 #ifdef OSL_GMP_IS_HERE
517  case OSL_PRECISION_MP: {
518  nb_read = gmp_sscanf(string, "%lZd", i->mp);
519  break;
520  }
521 #endif
522 
523  default:
524  OSL_error("unknown precision");
525  }
526 
527  if (nb_read == 0) { OSL_error("failed to read an integer"); }
528 
529  return nb_read;
530 }
531 
532 
539 void osl_int_sread(char ** string, int precision, osl_int_const_p i) {
540  // Update the position in the input string.
541  *string += osl_int_sscanf(*string, precision, i);
542 }
543 
544 
545 /*+***************************************************************************
546  * Arithmetic Operations *
547  *****************************************************************************/
548 
549 
556 void osl_int_increment(int precision,
557  osl_int_const_p variable, osl_const_int_t value) {
558  osl_int_add_si(precision, variable, value, 1);
559 }
560 
561 
568 void osl_int_decrement(int precision,
569  osl_int_const_p variable, osl_const_int_t value) {
570  osl_int_add_si(precision, variable, value, -1);
571 }
572 
573 
581 void osl_int_add(int precision, osl_int_const_p variable,
582  osl_const_int_t val1, osl_const_int_t val2) {
583  switch (precision) {
584  case OSL_PRECISION_SP:
585  #ifndef NDEBUG
586  if (osl_int_pos(precision, val1) && osl_int_pos(precision, val2)) {
587  if (LONG_MAX - val1.sp < val2.sp)
588  OSL_overflow("osl_int_add overflow");
589  }
590  else if (osl_int_neg(precision, val1) && osl_int_neg(precision, val2)) {
591  if (val1.sp - LONG_MIN < -val2.sp)
592  OSL_overflow("osl_int_add overflow");
593  }
594  #endif
595  variable->sp = val1.sp + val2.sp;
596  break;
597 
598  case OSL_PRECISION_DP:
599  #ifndef NDEBUG
600  if (osl_int_pos(precision, val1) && osl_int_pos(precision, val2)) {
601  if (LLONG_MAX - val1.dp < val2.dp)
602  OSL_overflow("osl_int_add overflow");
603  }
604  else if (osl_int_neg(precision, val1) && osl_int_neg(precision, val2)) {
605  if (val1.dp - LLONG_MIN < -val2.dp)
606  OSL_overflow("osl_int_add overflow");
607  }
608  #endif
609  variable->dp = val1.dp + val2.dp;
610  break;
611 
612 #ifdef OSL_GMP_IS_HERE
613  case OSL_PRECISION_MP:
614  mpz_add(*variable->mp, *val1.mp, *val2.mp);
615  break;
616 #endif
617 
618  default:
619  OSL_error("unknown precision");
620  }
621 }
622 
623 
631 void osl_int_add_si(int precision,
632  osl_int_const_p variable, osl_const_int_t value, int i) {
633  switch (precision) {
634  case OSL_PRECISION_SP:
635  #ifndef NDEBUG
636  if (osl_int_pos(precision, value) && i > 0) {
637  if (LONG_MAX - value.sp < i)
638  OSL_overflow("osl_int_add_si overflow");
639  }
640  else if (osl_int_neg(precision, value) && i < 0) {
641  if (value.sp - LONG_MIN < -i)
642  OSL_overflow("osl_int_add_si overflow");
643  }
644  #endif
645  variable->sp = value.sp + (long int)i;
646  break;
647 
648  case OSL_PRECISION_DP:
649  #ifndef NDEBUG
650  if (osl_int_pos(precision, value) && i > 0) {
651  if (LLONG_MAX - value.dp < i)
652  OSL_overflow("osl_int_add_si overflow");
653  }
654  else if (osl_int_neg(precision, value) && i < 0) {
655  if (value.dp - LLONG_MIN < -i)
656  OSL_overflow("osl_int_add_si overflow");
657  }
658  #endif
659  variable->dp = value.dp + (long long int)i;
660  break;
661 
662 #ifdef OSL_GMP_IS_HERE
663  case OSL_PRECISION_MP: {
664  mpz_t si;
665  mpz_init_set_si(si, i);
666  mpz_add(*variable->mp, *value.mp, si);
667  mpz_clear(si);
668  break;
669  }
670 #endif
671 
672  default:
673  OSL_error("unknown precision");
674  }
675 }
676 
677 
685 void osl_int_sub(int precision, osl_int_const_p variable,
686  osl_const_int_t val1, osl_const_int_t val2) {
687 #ifdef OSL_GMP_IS_HERE
688  if (precision == OSL_PRECISION_MP) {
689  mpz_sub(*variable->mp, *val1.mp, *val2.mp);
690  }
691  else
692 #endif
693  {
694  osl_int_t mval2; osl_int_init(precision, &mval2);
695  osl_int_oppose(precision, &mval2, val2);
696  osl_int_add(precision, variable, val1, mval2);
697  }
698 }
699 
700 
708 void osl_int_mul(int precision, osl_int_const_p variable,
709  osl_const_int_t val1, osl_const_int_t val2) {
710  switch (precision) {
711  case OSL_PRECISION_SP:
712  variable->sp = val1.sp * val2.sp;
713  #ifndef NDEBUG
714  if (!osl_int_zero(precision, val1) && !osl_int_zero(precision, val2)) {
715  if (variable->sp / val2.sp != val1.sp) {
716  OSL_overflow("osl_int_mul overflow");
717  }
718  }
719  #endif
720  break;
721 
722  case OSL_PRECISION_DP:
723  variable->dp = val1.dp * val2.dp;
724  #ifndef NDEBUG
725  if (!osl_int_zero(precision, val1) && !osl_int_zero(precision, val2)) {
726  if (variable->dp / val2.dp != val1.dp) {
727  OSL_overflow("osl_int_mul overflow");
728  }
729  }
730  #endif
731  break;
732 
733 #ifdef OSL_GMP_IS_HERE
734  case OSL_PRECISION_MP:
735  mpz_mul(*variable->mp, *val1.mp, *val2.mp);
736  break;
737 #endif
738 
739  default:
740  OSL_error("unknown precision");
741  }
742 }
743 
744 
752 void osl_int_mul_si(int precision,
753  osl_int_const_p variable, osl_const_int_t value, int i) {
754  switch (precision) {
755  case OSL_PRECISION_SP:
756  variable->sp = value.sp * (long int)i;
757  #ifndef NDEBUG
758  if (!osl_int_zero(precision, value) && i != 0) {
759  if (variable->sp / (long int)i != value.sp) {
760  OSL_overflow("osl_int_mul_si overflow");
761  }
762  }
763  #endif
764  break;
765 
766  case OSL_PRECISION_DP:
767  variable->dp = value.dp * (long long int)i;
768  #ifndef NDEBUG
769  if (!osl_int_zero(precision, value) && i != 0) {
770  if (variable->dp / (long long int)i != value.dp) {
771  OSL_overflow("osl_int_mul_si overflow");
772  }
773  }
774  #endif
775  break;
776 
777 #ifdef OSL_GMP_IS_HERE
778  case OSL_PRECISION_MP:
779  mpz_mul_si(*variable->mp, *value.mp, i);
780  break;
781 #endif
782 
783  default:
784  OSL_error("unknown precision");
785  }
786 }
787 
788 
797 void osl_int_div_exact(int const precision,
798  osl_int_const_p q,
800  switch (precision) {
801  case OSL_PRECISION_SP: q->sp = a.sp / b.sp; return;
802 
803  case OSL_PRECISION_DP: q->dp = a.dp / b.dp; return;
804 
805 #ifdef OSL_GMP_IS_HERE
806  case OSL_PRECISION_MP: mpz_divexact(*q->mp, *a.mp, *b.mp); return;
807 #endif
808 
809  default: OSL_error("unknown precision");
810  }
811 }
812 
813 
821 void osl_int_floor_div_q(int const precision,
822  osl_int_const_p q,
824  switch (precision) {
825  case OSL_PRECISION_SP:
826  q->sp = a.sp / b.sp;
827  if (q->sp < 0) { if (a.sp % b.sp != 0) --q->sp; }
828  else if (q->sp == 0) {
829  if ((osl_int_pos(precision, a) && osl_int_neg(precision, b)) ||
830  (osl_int_neg(precision, a) && osl_int_pos(precision, b))) {
831  --q->sp;
832  }
833  }
834  return;
835 
836  case OSL_PRECISION_DP:
837  q->dp = a.dp / b.dp;
838  if (q->dp < 0) { if (a.dp % b.dp != 0) --q->dp; }
839  else if (q->dp == 0) {
840  if ((osl_int_pos(precision, a) && osl_int_neg(precision, b)) ||
841  (osl_int_neg(precision, a) && osl_int_pos(precision, b))) {
842  --q->dp;
843  }
844  }
845  return;
846 
847 #ifdef OSL_GMP_IS_HERE
848  case OSL_PRECISION_MP: mpz_fdiv_q(*q->mp, *a.mp, *b.mp); return;
849 #endif
850 
851  default: OSL_error("unknown precision");
852  }
853 }
854 
855 
863 void osl_int_floor_div_r(int const precision,
864  osl_int_const_p r,
866  switch (precision) {
867  case OSL_PRECISION_SP:
868  osl_int_floor_div_q(precision, r, a, b);
869  r->sp = a.sp - r->sp * b.sp;
870  return;
871 
872  case OSL_PRECISION_DP:
873  osl_int_floor_div_q(precision, r, a, b);
874  r->dp = a.dp - r->dp * b.dp;
875  return;
876 
877 #ifdef OSL_GMP_IS_HERE
878  case OSL_PRECISION_MP: mpz_fdiv_r(*r->mp, *a.mp, *b.mp); return;
879 #endif
880 
881  default: OSL_error("unknown precision");
882  }
883 }
884 
885 
894 void osl_int_floor_div_q_r(int const precision,
897  switch (precision) {
898  case OSL_PRECISION_SP:
899  osl_int_floor_div_q(precision, q, a, b);
900  r->sp = a.sp - q->sp * b.sp;
901  return;
902 
903  case OSL_PRECISION_DP:
904  osl_int_floor_div_q(precision, q, a, b);
905  r->dp = a.dp - q->dp * b.dp;
906  return;
907 
908 #ifdef OSL_GMP_IS_HERE
909  case OSL_PRECISION_MP: mpz_fdiv_qr(*q->mp, *r->mp, *a.mp, *b.mp); return;
910 #endif
911 
912  default: OSL_error("unknown precision");
913  }
914 }
915 
916 
925 void osl_int_mod(int const precision, osl_int_const_p mod,
927  switch (precision) {
928  case OSL_PRECISION_SP:
929  mod->sp = a.sp % b.sp;
930  if (mod->sp < 0) mod->sp += labs(b.sp);
931  return;
932 
933  case OSL_PRECISION_DP:
934  mod->dp = a.dp % b.dp;
935  if (mod->dp < 0) mod->dp += llabs(b.dp);
936  return;
937 
938 #ifdef OSL_GMP_IS_HERE
939  case OSL_PRECISION_MP: mpz_mod(*mod->mp, *a.mp, *b.mp); return;
940 #endif
941 
942  default: OSL_error("unknown precision");
943  }
944 }
945 
946 
947 // gcd (greatest common divisor) for long long int
948 static long long int llgcd(long long int const a, long long int const b) {
949  return (b ? llgcd(b, a % b) : a);
950 }
951 
959 void osl_int_gcd(int const precision, osl_int_const_p gcd,
961  switch (precision) {
962  case OSL_PRECISION_SP: gcd->sp = labs(llgcd(a.sp, b.sp)); return;
963 
964  case OSL_PRECISION_DP: gcd->dp = llabs(llgcd(a.dp, b.dp)); return;
965 
966 #ifdef OSL_GMP_IS_HERE
967  case OSL_PRECISION_MP: mpz_gcd(*gcd->mp, *a.mp, *b.mp); return;
968 #endif
969 
970  default: OSL_error("unknown precision");
971  }
972 }
973 
974 
981 void osl_int_oppose(int precision,
982  osl_int_const_p variable, osl_const_int_t value) {
983  switch (precision) {
984  case OSL_PRECISION_SP:
985  variable->sp = -value.sp;
986  break;
987 
988  case OSL_PRECISION_DP:
989  variable->dp = -value.dp;
990  break;
991 
992 #ifdef OSL_GMP_IS_HERE
993  case OSL_PRECISION_MP:
994  mpz_neg(*variable->mp, *value.mp);
995  break;
996 #endif
997 
998  default:
999  OSL_error("unknown precision");
1000  }
1001 }
1002 
1003 
1010 void osl_int_abs(int precision,
1011  osl_int_const_p variable, osl_const_int_t value) {
1012  switch (precision) {
1013  case OSL_PRECISION_SP:
1014  variable->sp = (value.sp > 0) ? value.sp : -value.sp;
1015  break;
1016 
1017  case OSL_PRECISION_DP:
1018  variable->dp = (value.dp > 0) ? value.dp : -value.dp;
1019  break;
1020 
1021 #ifdef OSL_GMP_IS_HERE
1022  case OSL_PRECISION_MP:
1023  mpz_abs(*variable->mp, *value.mp);
1024  break;
1025 #endif
1026 
1027  default:
1028  OSL_error("unknown precision");
1029  }
1030 }
1031 
1032 
1033 // log2 function for long long int
1034 static size_t lllog2(long long int x) {
1035  size_t n = 0;
1036 
1037  x = llabs(x);
1038 
1039  while (x) { x >>= 1; ++n; }
1040 
1041  return ((n == 0) ? 1 : n);
1042 }
1043 
1050 size_t osl_int_size_in_base_2(int const precision,
1051  osl_const_int_t const value) {
1052  switch (precision) {
1053  case OSL_PRECISION_SP: return lllog2(value.sp);
1054 
1055  case OSL_PRECISION_DP: return lllog2(value.dp);
1056 
1057 #ifdef OSL_GMP_IS_HERE
1058  case OSL_PRECISION_MP: return mpz_sizeinbase(*value.mp, 2);
1059 #endif
1060 
1061  default: OSL_error("unknown precision");
1062  }
1063 }
1064 
1065 
1066 // log10 function for long long int
1067 static size_t lllog10(long long int x) {
1068  size_t n = 0;
1069 
1070  x = llabs(x);
1071 
1072  while (x) { x /= 10; ++n; }
1073 
1074  return n;
1075 }
1076 
1084 size_t osl_int_size_in_base_10(int const precision,
1085  osl_const_int_t const value) {
1086  switch (precision) {
1087  case OSL_PRECISION_SP: return lllog10(value.sp);
1088 
1089  case OSL_PRECISION_DP: return lllog10(value.dp);
1090 
1091 #ifdef OSL_GMP_IS_HERE
1092  case OSL_PRECISION_MP: return mpz_sizeinbase(*value.mp, 10);
1093 #endif
1094 
1095  default: OSL_error("unknown precision");
1096  }
1097 }
1098 
1099 
1100 /*+***************************************************************************
1101  * Conditional Operations *
1102  *****************************************************************************/
1103 
1104 
1112 int osl_int_eq(int precision, osl_const_int_t val1, osl_const_int_t val2) {
1113  switch (precision) {
1114  case OSL_PRECISION_SP:
1115  return (val1.sp == val2.sp);
1116 
1117  case OSL_PRECISION_DP:
1118  return (val1.dp == val2.dp);
1119 
1120 #ifdef OSL_GMP_IS_HERE
1121  case OSL_PRECISION_MP:
1122  return (mpz_cmp(*val1.mp, *val2.mp) == 0);
1123 #endif
1124 
1125  default:
1126  OSL_error("unknown precision");
1127  }
1128 }
1129 
1130 
1138 int osl_int_ne(int precision, osl_const_int_t val1, osl_const_int_t val2) {
1139  return !osl_int_eq(precision, val1, val2);
1140 }
1141 
1142 
1149 int osl_int_pos(int precision, osl_const_int_t value) {
1150  switch (precision) {
1151  case OSL_PRECISION_SP:
1152  return (value.sp > 0);
1153 
1154  case OSL_PRECISION_DP:
1155  return (value.dp > 0);
1156 
1157 #ifdef OSL_GMP_IS_HERE
1158  case OSL_PRECISION_MP:
1159  return (mpz_sgn(*value.mp) > 0);
1160 #endif
1161 
1162  default:
1163  OSL_error("unknown precision");
1164  }
1165 }
1166 
1167 
1174 int osl_int_neg(int precision, osl_const_int_t value) {
1175  switch (precision) {
1176  case OSL_PRECISION_SP:
1177  return (value.sp < 0);
1178 
1179  case OSL_PRECISION_DP:
1180  return (value.dp < 0);
1181 
1182 #ifdef OSL_GMP_IS_HERE
1183  case OSL_PRECISION_MP:
1184  return (mpz_sgn(*value.mp) < 0);
1185 #endif
1186 
1187  default:
1188  OSL_error("unknown precision");
1189  }
1190 }
1191 
1192 
1199 int osl_int_zero(int precision, osl_const_int_t value) {
1200  switch (precision) {
1201  case OSL_PRECISION_SP:
1202  return (value.sp == 0);
1203 
1204  case OSL_PRECISION_DP:
1205  return (value.dp == 0);
1206 
1207 #ifdef OSL_GMP_IS_HERE
1208  case OSL_PRECISION_MP:
1209  return (mpz_sgn(*value.mp) == 0);
1210 #endif
1211 
1212  default:
1213  OSL_error("unknown precision");
1214  }
1215 }
1216 
1217 
1224 int osl_int_one(int precision, osl_const_int_t value) {
1225  switch (precision) {
1226  case OSL_PRECISION_SP:
1227  return (value.sp == (long int)1);
1228 
1229  case OSL_PRECISION_DP:
1230  return (value.dp == (long long int)1);
1231 
1232 #ifdef OSL_GMP_IS_HERE
1233  case OSL_PRECISION_MP:
1234  return (mpz_cmp_si(*value.mp, 1) == 0);
1235 #endif
1236 
1237  default:
1238  OSL_error("unknown precision");
1239  }
1240 }
1241 
1242 
1249 int osl_int_mone(int precision, osl_const_int_t value) {
1250  switch (precision) {
1251  case OSL_PRECISION_SP:
1252  return (value.sp == (long int)-1);
1253 
1254  case OSL_PRECISION_DP:
1255  return (value.dp == (long long int)-1);
1256 
1257 #ifdef OSL_GMP_IS_HERE
1258  case OSL_PRECISION_MP:
1259  return (mpz_cmp_si(*value.mp, -1) == 0);
1260 #endif
1261 
1262  default:
1263  OSL_error("unknown precision");
1264  }
1265 }
1266 
1267 
1275 int osl_int_divisible(int precision,
1276  osl_const_int_t val1, osl_const_int_t val2) {
1277  switch (precision) {
1278  case OSL_PRECISION_SP:
1279  return ((val1.sp % val2.sp) == 0);
1280 
1281  case OSL_PRECISION_DP:
1282  return ((val1.dp % val2.dp) == 0);
1283 
1284 #ifdef OSL_GMP_IS_HERE
1285  case OSL_PRECISION_MP:
1286  return mpz_divisible_p(*val1.mp, *val2.mp);
1287 #endif
1288 
1289  default:
1290  OSL_error("unknown precision");
1291  }
1292 }
1293 
1294 
1295 /*+***************************************************************************
1296  * Processing functions *
1297  *****************************************************************************/
1298 
1299 
1306 void osl_int_set_precision(int const precision, int const new_precision,
1307  osl_int_p i) {
1308  if (i != NULL && precision != new_precision) {
1309  int v = osl_int_get_si(precision, *i); // TODO Fix to avoid overflow
1310  osl_int_clear(precision, i);
1311  osl_int_init_set_si(new_precision, i, v);
1312  }
1313 }
int osl_int_get_si(int precision, osl_const_int_t value)
Get the value in a int.
Definition: int.c:236
void osl_int_init_set(int precision, osl_int_const_p variable, osl_const_int_t i)
variable = i // including initialization for GMP
Definition: int.c:302
int osl_int_one(int precision, osl_const_int_t value)
value == 1
Definition: int.c:1224
union osl_int *const osl_int_const_p
Definition: int.h:91
void osl_int_oppose(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = - value
Definition: int.c:981
int osl_int_divisible(int precision, osl_const_int_t val1, osl_const_int_t val2)
(val1 % val2) == 0
Definition: int.c:1275
void osl_int_free(int precision, osl_int_const_p variable)
Free thr osl int.
Definition: int.c:410
void osl_int_swap(int precision, osl_int_const_p var1, osl_int_const_p var2)
Swap the osl ints.
Definition: int.c:343
void osl_int_gcd(int const precision, osl_int_const_p gcd, osl_const_int_t a, osl_const_int_t b)
Compute the gcd (greatest common divisor) of a and b.
Definition: int.c:959
int osl_int_mone(int precision, osl_const_int_t value)
value == -1
Definition: int.c:1249
void osl_int_sread(char **string, int precision, osl_int_const_p i)
sread for osl int
Definition: int.c:539
int osl_int_neg(int precision, osl_const_int_t value)
value < 0
Definition: int.c:1174
int osl_int_is_precision_supported(int precision)
Definition: int.c:90
union osl_int const osl_const_int_t
Definition: int.h:90
int osl_int_ne(int precision, osl_const_int_t val1, osl_const_int_t val2)
val1 != val2
Definition: int.c:1138
void osl_int_sub(int precision, osl_int_const_p variable, osl_const_int_t val1, osl_const_int_t val2)
variable = val1 - val2
Definition: int.c:685
size_t osl_int_size_in_base_2(int const precision, osl_const_int_t const value)
Get the size in base 2.
Definition: int.c:1050
void osl_int_increment(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = value + 1
Definition: int.c:556
size_t osl_int_size_in_base_10(int const precision, osl_const_int_t const value)
Get the size in base 10.
Definition: int.c:1084
void osl_int_mul(int precision, osl_int_const_p variable, osl_const_int_t val1, osl_const_int_t val2)
variable = val1 * val2
Definition: int.c:708
void osl_int_clear(int precision, osl_int_const_p variable)
variable = 0 // including cleaning for GMP
Definition: int.c:382
double osl_int_get_d(int precision, osl_const_int_t i)
Get the value in a double.
Definition: int.c:277
static size_t lllog10(long long int x)
Definition: int.c:1067
Definition: int.h:79
void osl_int_floor_div_r(int const precision, osl_int_const_p r, osl_const_int_t a, osl_const_int_t b)
r = a - b * (a / b)
Definition: int.c:863
void osl_int_set_precision(int const precision, int const new_precision, osl_int_p i)
Change the precision of the osl_int.
Definition: int.c:1306
void osl_int_init_set_si(int precision, osl_int_const_p variable, int i)
variable = i // including initialization for GMP
Definition: int.c:314
int osl_int_eq(int precision, osl_const_int_t val1, osl_const_int_t val2)
val1 == val2
Definition: int.c:1112
void osl_int_print(FILE *file, int precision, osl_const_int_t value)
Definition: int.c:423
void osl_int_init(int precision, osl_int_const_p variable)
Initialize the osl int.
Definition: int.c:137
void osl_int_abs(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = | value |
Definition: int.c:1010
void osl_int_set_si(int precision, osl_int_const_p variable, int i)
variable = i
Definition: int.c:208
void osl_int_sprint_txt(char *string, int precision, osl_const_int_t value)
Definition: int.c:471
void osl_int_add(int precision, osl_int_const_p variable, osl_const_int_t val1, osl_const_int_t val2)
variable = val1 + val2
Definition: int.c:581
void osl_int_floor_div_q(int const precision, osl_int_const_p q, osl_const_int_t a, osl_const_int_t b)
q = floor(a / b)
Definition: int.c:821
static size_t lllog2(long long int x)
Definition: int.c:1034
static long long int llgcd(long long int const a, long long int const b)
Definition: int.c:948
void osl_int_div_exact(int const precision, osl_int_const_p q, osl_const_int_t a, osl_const_int_t b)
q = a / b
Definition: int.c:797
void osl_int_floor_div_q_r(int const precision, osl_int_const_p q, osl_int_const_p r, osl_const_int_t a, osl_const_int_t b)
Compute (q, r) such that a = b * q + r.
Definition: int.c:894
int osl_int_sscanf(char *string, int precision, osl_int_const_p i)
sscanf for osl int
Definition: int.c:504
void osl_int_add_si(int precision, osl_int_const_p variable, osl_const_int_t value, int i)
variable = val1 + i
Definition: int.c:631
void osl_int_sprint(char *string, int precision, osl_const_int_t value)
Definition: int.c:439
osl_int_p osl_int_malloc(int precision)
Initialize the osl int.
Definition: int.c:164
void osl_int_assign(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = value
Definition: int.c:179
void osl_int_mul_si(int precision, osl_int_const_p variable, osl_const_int_t value, int i)
variable = val1 * i
Definition: int.c:752
int osl_int_zero(int precision, osl_const_int_t value)
value == 0
Definition: int.c:1199
int osl_int_pos(int precision, osl_const_int_t value)
value > 0
Definition: int.c:1149
void osl_int_decrement(int precision, osl_int_const_p variable, osl_const_int_t value)
variable = value - 1
Definition: int.c:568
void osl_int_mod(int const precision, osl_int_const_p mod, osl_const_int_t a, osl_const_int_t b)
mod = a % b
Definition: int.c:925
void osl_int_dump_precision(FILE *file, int precision)
Definition: int.c:113