Replace openscop_ prefix with osl_ to ease 80 columns programming
[openscop.git] / source / int.c
blob293c191a63953d249dcd0f0efc4a5ef7f240c31a
2 /*+-----------------------------------------------------------------**
3 ** OpenScop Library **
4 **-----------------------------------------------------------------**
5 ** int.c **
6 **-----------------------------------------------------------------**
7 ** First version: 18/07/2011 **
8 **-----------------------------------------------------------------**
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 *****************************************************************************/
63 # include <stdlib.h>
64 # include <stdio.h>
65 # include <osl/int.h>
68 /*+***************************************************************************
69 * Basic Functions *
70 *****************************************************************************/
73 /**
74 * osl_int_dump_precision function:
75 * this function prints in a human readable fashion the precision
76 * corresponding to the "precision" parameter.
77 * \param[in] file The file where to print the precision.
78 * \param[in] precision The precision to print.
80 void osl_int_dump_precision(FILE * file, int precision) {
82 switch (precision) {
83 case OSL_PRECISION_SP:
84 fprintf(file, "32 bits");
85 break;
86 case OSL_PRECISION_DP:
87 fprintf(file, "64 bits");
88 break;
89 #ifdef OSL_GMP_IS_HERE
90 case OSL_PRECISION_MP:
91 fprintf(file, "GMP");
92 break;
93 #endif
94 default:
95 fprintf(file, "unknown precision %d", precision);
100 int osl_int_sizeof(int precision) {
101 switch (precision) {
102 case OSL_PRECISION_SP:
103 return sizeof(long int);
105 case OSL_PRECISION_DP:
106 return sizeof(long long int);
108 #ifdef OSL_GMP_IS_HERE
109 case OSL_PRECISION_MP:
110 return sizeof(mpz_t);
111 #endif
113 default:
114 OSL_error("unknown precision");
119 void * osl_int_address(int precision, void * base, int offset) {
120 switch (precision) {
121 case OSL_PRECISION_SP:
122 return (long int *)base + offset;
124 case OSL_PRECISION_DP:
125 return (long long int *)base + offset;
127 #ifdef OSL_GMP_IS_HERE
128 case OSL_PRECISION_MP:
129 return (mpz_t *)base + offset;
130 #endif
132 default:
133 OSL_error("unknown precision");
138 void osl_int_init(int precision, void * value_base, int value_offset) {
139 void * value = osl_int_address(precision, value_base, value_offset);
141 switch (precision) {
142 case OSL_PRECISION_SP:
143 *(long int *)value = 0;
144 break;
146 case OSL_PRECISION_DP:
147 *(long long int *)value = 0;
148 break;
150 #ifdef OSL_GMP_IS_HERE
151 case OSL_PRECISION_MP:
152 mpz_init(*(mpz_t *)value);
153 break;
154 #endif
156 default:
157 OSL_error("unknown precision");
162 void * osl_int_malloc(int precision) {
163 void * value;
165 switch (precision) {
166 case OSL_PRECISION_SP:
167 value = malloc(sizeof(long int));
168 break;
170 case OSL_PRECISION_DP:
171 value = malloc(sizeof(long long int));
172 *(long long int *)value = 0;
173 break;
175 #ifdef OSL_GMP_IS_HERE
176 case OSL_PRECISION_MP:
177 value = malloc(sizeof(mpz_t));
178 break;
179 #endif
181 default:
182 OSL_error("unknown precision");
185 osl_int_init(precision, value, 0);
186 return value;
190 void osl_int_assign(int precision,
191 void * val1_base, int val1_offset,
192 void * val2_base, int val2_offset) {
193 void * val1 = osl_int_address(precision, val1_base, val1_offset);
194 void * val2 = osl_int_address(precision, val2_base, val2_offset);
196 switch (precision) {
197 case OSL_PRECISION_SP:
198 *(long int *)val1 = *(long int *)val2;
199 break;
201 case OSL_PRECISION_DP:
202 *(long long int *)val1 = *(long long int *)val2;
203 break;
205 #ifdef OSL_GMP_IS_HERE
206 case OSL_PRECISION_MP:
207 mpz_set(*(mpz_t *)val1, *(mpz_t *)val2);
208 break;
209 #endif
211 default:
212 OSL_error("unknown precision");
217 void osl_int_set_si(int precision, void * value_base, int value_offset,
218 int i) {
219 void * value = osl_int_address(precision, value_base, value_offset);
221 switch (precision) {
222 case OSL_PRECISION_SP:
223 *(long int *)value = (long int)i;
224 break;
226 case OSL_PRECISION_DP:
227 *(long long int *)value = (long long int)i;
228 break;
230 #ifdef OSL_GMP_IS_HERE
231 case OSL_PRECISION_MP:
232 mpz_set_si(*(mpz_t *)value, i);
233 break;
234 #endif
236 default:
237 OSL_error("unknown precision");
242 int osl_int_get_si(int precision, void * value_base, int value_offset) {
243 void * value = osl_int_address(precision, value_base, value_offset);
245 switch (precision) {
246 case OSL_PRECISION_SP:
247 return *(int *)value;
249 case OSL_PRECISION_DP:
250 return *(int *)value;
252 #ifdef OSL_GMP_IS_HERE
253 case OSL_PRECISION_MP:
254 return mpz_get_si(*(mpz_t *)value);
255 #endif
257 default:
258 OSL_error("unknown precision");
263 void osl_int_init_set_si(int precision,
264 void * value_base, int value_offset, int i) {
265 void * value = osl_int_address(precision, value_base, value_offset);
267 switch (precision) {
268 case OSL_PRECISION_SP:
269 *(long int *)value = (long int)i;
270 break;
272 case OSL_PRECISION_DP:
273 *(long long int *)value = (long long int)i;
274 break;
276 #ifdef OSL_GMP_IS_HERE
277 case OSL_PRECISION_MP:
278 mpz_init_set_si(*(mpz_t *)value, i);
279 break;
280 #endif
282 default:
283 OSL_error("unknown precision");
288 void osl_int_clear(int precision, void * value_base, int value_offset) {
289 void * value = osl_int_address(precision, value_base, value_offset);
291 switch (precision) {
292 case OSL_PRECISION_SP:
293 *(long int *)value = 0;
294 break;
296 case OSL_PRECISION_DP:
297 *(long long int *)value = 0;
298 break;
300 #ifdef OSL_GMP_IS_HERE
301 case OSL_PRECISION_MP:
302 mpz_clear(*(mpz_t *)value);
303 break;
304 #endif
306 default:
307 OSL_error("unknown precision");
312 void osl_int_free(int precision, void * value_base, int value_offset) {
313 void * value = osl_int_address(precision, value_base, value_offset);
315 osl_int_clear(precision, value_base, value_offset);
316 free(value);
321 * osl_int_print function:
322 * this function displays an integer value into a file (file, possibly stdout).
323 * \param file The file where the integer has to be printed.
324 * \param precision The precision of the integer.
325 * \param value Address of the integer value.
327 void osl_int_print(FILE * file, int precision,
328 void * value_base, int value_offset) {
329 char string[OSL_MAX_STRING];
331 osl_int_sprint(string, precision, value_base, value_offset);
332 fprintf(file, "%s", string);
337 * osl_int_sprint function:
338 * this function prints an integer value into a string.
339 * \param string The string where the integer has to be printed.
340 * \param precision The precision of the integer.
341 * \param value Address of the integer value.
343 void osl_int_sprint(char * string, int precision,
344 void * value_base, int value_offset) {
345 void * value = osl_int_address(precision, value_base, value_offset);
347 switch (precision) {
348 case OSL_PRECISION_SP:
349 sprintf(string, OSL_FMT_SP, *(long int *)value);
350 break;
352 case OSL_PRECISION_DP:
353 sprintf(string, OSL_FMT_DP, *(long long int *)value);
354 break;
356 #ifdef OSL_GMP_IS_HERE
357 case OSL_PRECISION_MP: {
358 char * str;
359 str = mpz_get_str(0, 10, *(mpz_t *)value); //TODO: 10 -> #define
360 sprintf(string, OSL_FMT_MP, str);
361 free(str);
362 break;
364 #endif
366 default:
367 OSL_error("unknown precision");
372 void osl_int_sread(char * string, int precision,
373 void * value_base, int value_offset) {
374 void * value = osl_int_address(precision, value_base, value_offset);
375 int nb_read;
377 switch (precision) {
378 case OSL_PRECISION_SP:
379 nb_read = sscanf(string, OSL_FMT_TXT_SP, (long int *)value);
380 if (nb_read == 0)
381 OSL_error("failed to read an integer");
382 break;
384 case OSL_PRECISION_DP:
385 nb_read = sscanf(string, OSL_FMT_TXT_DP, (long long int *)value);
386 if (nb_read == 0)
387 OSL_error("failed to read an integer");
388 break;
390 #ifdef OSL_GMP_IS_HERE
391 case OSL_PRECISION_MP: {
392 long long int tmp;
393 nb_read = sscanf(string, OSL_FMT_TXT_DP, &tmp);
394 if (nb_read == 0)
395 OSL_error("failed to read an integer");
396 mpz_set_si(*(mpz_t *)value, tmp);
397 break;
399 #endif
401 default:
402 OSL_error("unknown precision");
407 /*+***************************************************************************
408 * Arithmetic Operations *
409 *****************************************************************************/
412 void osl_int_increment(int precision,
413 void * result_base, int result_offset,
414 void * value_base, int value_offset) {
415 void * result = osl_int_address(precision, result_base, result_offset);
416 void * value = osl_int_address(precision, value_base, value_offset);
418 switch (precision) {
419 case OSL_PRECISION_SP:
420 *(long int *)result = *(long int *)value + (long int)1;
421 break;
423 case OSL_PRECISION_DP:
424 *(long long int *)result = *(long long int *)value + (long long int)1;
425 break;
427 #ifdef OSL_GMP_IS_HERE
428 case OSL_PRECISION_MP:
429 mpz_add_ui(*(mpz_t *)result, *(mpz_t *)value, 1);
430 break;
431 #endif
433 default:
434 OSL_error("unknown precision");
439 void osl_int_decrement(int precision,
440 void * result_base, int result_offset,
441 void * value_base, int value_offset) {
442 void * result = osl_int_address(precision, result_base, result_offset);
443 void * value = osl_int_address(precision, value_base, value_offset);
445 switch (precision) {
446 case OSL_PRECISION_SP:
447 *(long int *)result = *(long int *)value - (long int)1;
448 break;
450 case OSL_PRECISION_DP:
451 *(long long int *)result = *(long long int *)value - (long long int)1;
452 break;
454 #ifdef OSL_GMP_IS_HERE
455 case OSL_PRECISION_MP: {
456 mpz_t one;
457 mpz_init_set_si(one, 1);
458 mpz_sub(*(mpz_t *)result, *(mpz_t *)value, one);
459 mpz_clear(one);
460 break;
462 #endif
464 default:
465 OSL_error("unknown precision");
470 void osl_int_add(int precision,
471 void * result_base, int result_offset,
472 void * val1_base, int val1_offset,
473 void * val2_base, int val2_offset) {
474 void * result = osl_int_address(precision, result_base, result_offset);
475 void * val1 = osl_int_address(precision, val1_base, val1_offset);
476 void * val2 = osl_int_address(precision, val2_base, val2_offset);
478 switch (precision) {
479 case OSL_PRECISION_SP:
480 *(long int *)result = *(long int *)val1 + *(long int *)val2;
481 break;
483 case OSL_PRECISION_DP:
484 *(long long int *)result = *(long long int *)val1 +
485 *(long long int *)val2;
486 break;
488 #ifdef OSL_GMP_IS_HERE
489 case OSL_PRECISION_MP:
490 mpz_add(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
491 break;
492 #endif
494 default:
495 OSL_error("unknown precision");
500 void osl_int_add_ui(int precision,
501 void * result_base, int result_offset,
502 void * value_base, int value_offset, int i) {
503 void * result = osl_int_address(precision, result_base, result_offset);
504 void * value = osl_int_address(precision, value_base, value_offset);
506 switch (precision) {
507 case OSL_PRECISION_SP:
508 *(long int *)result = *(long int *)value + (long int)i;
509 break;
511 case OSL_PRECISION_DP:
512 *(long long int *)result = *(long long int *)value + (long long int)i;
513 break;
515 #ifdef OSL_GMP_IS_HERE
516 case OSL_PRECISION_MP:
517 mpz_add_ui(*(mpz_t *)result, *(mpz_t *)value, (long int)i);
518 break;
519 #endif
521 default:
522 OSL_error("unknown precision");
527 void osl_int_mul(int precision,
528 void * result_base, int result_offset,
529 void * val1_base, int val1_offset,
530 void * val2_base, int val2_offset) {
531 void * result = osl_int_address(precision, result_base, result_offset);
532 void * val1 = osl_int_address(precision, val1_base, val1_offset);
533 void * val2 = osl_int_address(precision, val2_base, val2_offset);
535 switch (precision) {
536 case OSL_PRECISION_SP:
537 *(long int *)result = *(long int *)val1 * *(long int *)val2;
538 break;
540 case OSL_PRECISION_DP:
541 *(long long int *)result = *(long long int *)val1 *
542 *(long long int *)val2;
543 break;
545 #ifdef OSL_GMP_IS_HERE
546 case OSL_PRECISION_MP:
547 mpz_mul(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
548 break;
549 #endif
551 default:
552 OSL_error("unknown precision");
557 void osl_int_mul_si(int precision,
558 void * result_base, int result_offset,
559 void * value_base, int value_offset, int i) {
560 void * result = osl_int_address(precision, result_base, result_offset);
561 void * value = osl_int_address(precision, value_base, value_offset);
563 switch (precision) {
564 case OSL_PRECISION_SP:
565 *(long int *)result = *(long int *)value * (long int)i;
566 break;
568 case OSL_PRECISION_DP:
569 *(long long int *)result = *(long long int *)value * (long long int)i;
570 break;
572 #ifdef OSL_GMP_IS_HERE
573 case OSL_PRECISION_MP:
574 mpz_mul_si(*(mpz_t *)result, *(mpz_t *)value, i);
575 break;
576 #endif
578 default:
579 OSL_error("unknown precision");
584 void osl_int_sub(int precision,
585 void * result_base, int result_offset,
586 void * val1_base, int val1_offset,
587 void * val2_base, int val2_offset) {
588 void * result = osl_int_address(precision, result_base, result_offset);
589 void * val1 = osl_int_address(precision, val1_base, val1_offset);
590 void * val2 = osl_int_address(precision, val2_base, val2_offset);
592 switch (precision) {
593 case OSL_PRECISION_SP:
594 *(long int *)result = *(long int *)val1 - *(long int *)val2;
595 break;
597 case OSL_PRECISION_DP:
598 *(long long int *)result = *(long long int *)val1 -
599 *(long long int *)val2;
600 break;
602 #ifdef OSL_GMP_IS_HERE
603 case OSL_PRECISION_MP:
604 mpz_sub(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
605 break;
606 #endif
608 default:
609 OSL_error("unknown precision");
614 void osl_int_oppose(int precision,
615 void * result_base, int result_offset,
616 void * value_base, int value_offset) {
617 void * result = osl_int_address(precision, result_base, result_offset);
618 void * value = osl_int_address(precision, value_base, value_offset);
620 switch (precision) {
621 case OSL_PRECISION_SP:
622 *(long int *)result = -*(long int *)value;
623 break;
625 case OSL_PRECISION_DP:
626 *(long long int *)result = -*(long long int *)value;
627 break;
629 #ifdef OSL_GMP_IS_HERE
630 case OSL_PRECISION_MP:
631 mpz_neg(*(mpz_t *)result, *(mpz_t *)value);
632 break;
633 #endif
635 default:
636 OSL_error("unknown precision");
641 /*+***************************************************************************
642 * Conditional Operations *
643 *****************************************************************************/
646 int osl_int_eq(int precision,
647 void * val1_base, int val1_offset,
648 void * val2_base, int val2_offset) {
649 void * val1 = osl_int_address(precision, val1_base, val1_offset);
650 void * val2 = osl_int_address(precision, val2_base, val2_offset);
652 switch (precision) {
653 case OSL_PRECISION_SP:
654 return (*(long int *)val1 == *(long int *)val2);
656 case OSL_PRECISION_DP:
657 return (*(long long int *)val1 == *(long long int *)val2);
659 #ifdef OSL_GMP_IS_HERE
660 case OSL_PRECISION_MP:
661 return (mpz_cmp(*(mpz_t *)val1, *(mpz_t *)val2) == 0);
662 #endif
664 default:
665 OSL_error("unknown precision");
670 int osl_int_ne(int precision,
671 void * val1_base, int val1_offset,
672 void * val2_base, int val2_offset) {
673 return !osl_int_eq(precision,
674 val1_base, val1_offset,
675 val2_base, val2_offset);
679 int osl_int_pos(int precision, void * value_base, int value_offset) {
680 void * value = osl_int_address(precision, value_base, value_offset);
682 switch (precision) {
683 case OSL_PRECISION_SP:
684 return (*(long int *)value > 0);
686 case OSL_PRECISION_DP:
687 return (*(long long int *)value > 0);
689 #ifdef OSL_GMP_IS_HERE
690 case OSL_PRECISION_MP:
691 return (mpz_sgn(*(mpz_t *)value) > 0);
692 #endif
694 default:
695 OSL_error("unknown precision");
700 int osl_int_neg(int precision, void * value_base, int value_offset) {
701 void * value = osl_int_address(precision, value_base, value_offset);
703 switch (precision) {
704 case OSL_PRECISION_SP:
705 return (*(long int *)value < 0);
707 case OSL_PRECISION_DP:
708 return (*(long long int *)value < 0);
710 #ifdef OSL_GMP_IS_HERE
711 case OSL_PRECISION_MP:
712 return (mpz_sgn(*(mpz_t *)value) < 0);
713 #endif
715 default:
716 OSL_error("unknown precision");
721 int osl_int_zero(int precision, void * value_base, int value_offset) {
722 void * value = osl_int_address(precision, value_base, value_offset);
724 switch (precision) {
725 case OSL_PRECISION_SP:
726 return (*(long int *)value == 0);
728 case OSL_PRECISION_DP:
729 return (*(long long int *)value == 0);
731 #ifdef OSL_GMP_IS_HERE
732 case OSL_PRECISION_MP:
733 return (mpz_sgn(*(mpz_t *)value) == 0);
734 #endif
736 default:
737 OSL_error("unknown precision");
742 int osl_int_notzero(int precision, void * value_base, int value_offset) {
744 return !osl_int_zero(precision, value_base, value_offset);
748 int osl_int_one(int precision, void * value_base, int value_offset) {
749 void * value = osl_int_address(precision, value_base, value_offset);
751 switch (precision) {
752 case OSL_PRECISION_SP:
753 return (*(long int *)value == (long int)1);
755 case OSL_PRECISION_DP:
756 return (*(long long int *)value == (long long int)1);
758 #ifdef OSL_GMP_IS_HERE
759 case OSL_PRECISION_MP:
760 return (mpz_cmp_si(*(mpz_t *)value, 1) == 0);
761 #endif
763 default:
764 OSL_error("unknown precision");
769 int osl_int_mone(int precision, void * value_base, int value_offset) {
770 void * value = osl_int_address(precision, value_base, value_offset);
772 switch (precision) {
773 case OSL_PRECISION_SP:
774 return (*(long int *)value == (long int)-1);
776 case OSL_PRECISION_DP:
777 return (*(long long int *)value == (long long int)-1);
779 #ifdef OSL_GMP_IS_HERE
780 case OSL_PRECISION_MP:
781 return (mpz_cmp_si(*(mpz_t *)value, -1) == 0);
782 #endif
784 default:
785 OSL_error("unknown precision");
790 int osl_int_divisible(int precision,
791 void * val1_base, int val1_offset,
792 void * val2_base, int val2_offset) {
793 void * val1 = osl_int_address(precision, val1_base, val1_offset);
794 void * val2 = osl_int_address(precision, val2_base, val2_offset);
796 switch (precision) {
797 case OSL_PRECISION_SP:
798 return ((*(long int *)val1 % *(long int *)val2) == 0);
800 case OSL_PRECISION_DP:
801 return ((*(long long int *)val1 % *(long long int *)val2) == 0);
803 #ifdef OSL_GMP_IS_HERE
804 case OSL_PRECISION_MP:
805 return mpz_divisible_p(*(mpz_t *)val1, *(mpz_t *)val2);
806 #endif
808 default:
809 OSL_error("unknown precision");