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#ifdef OSL_GMP_IS_HERE
66# include <gmp.h>
67#endif
68
69#include <osl/macros.h>
70#include <osl/int.h>
71
72
73
74/*+***************************************************************************
75 *                                Basic Functions                            *
76 *****************************************************************************/
77
78
79/**
80 * osl_int_dump_precision function:
81 * this function prints in a human readable fashion the precision
82 * corresponding to the "precision" parameter.
83 * \param[in] file      The file where to print the precision.
84 * \param[in] precision The precision to print.
85 */
86void osl_int_dump_precision(FILE * file, int precision) {
87
88  switch (precision) {
89    case OSL_PRECISION_SP:
90      fprintf(file, "32 bits");
91      break;
92    case OSL_PRECISION_DP:
93      fprintf(file, "64 bits");
94      break;
95#ifdef OSL_GMP_IS_HERE
96    case OSL_PRECISION_MP:
97      fprintf(file, "GMP");
98      break;
99#endif
100    default:
101      fprintf(file, "unknown precision %d", precision);
102  }
103}
104
105
106int osl_int_sizeof(int precision) {
107  switch (precision) {
108    case OSL_PRECISION_SP:
109      return sizeof(long int);
110
111    case OSL_PRECISION_DP:
112      return sizeof(long long int);
113
114#ifdef OSL_GMP_IS_HERE
115    case OSL_PRECISION_MP:
116      return sizeof(mpz_t);
117#endif
118
119    default:
120      OSL_error("unknown precision");
121  }
122}
123
124
125void * osl_int_address(int precision, void * base, int offset) {
126  switch (precision) {
127    case OSL_PRECISION_SP:
128      return (long int *)base + offset;
129
130    case OSL_PRECISION_DP:
131      return (long long int *)base + offset;
132
133#ifdef OSL_GMP_IS_HERE
134    case OSL_PRECISION_MP:
135      return (mpz_t *)base + offset;
136#endif
137
138    default:
139      OSL_error("unknown precision");
140  }
141}
142
143
144void osl_int_init(int precision, void * value_base, int value_offset) {
145  void * value = osl_int_address(precision, value_base, value_offset);
146
147  switch (precision) {
148    case OSL_PRECISION_SP:
149      *(long int *)value = 0;
150      break;
151
152    case OSL_PRECISION_DP:
153      *(long long int *)value = 0;
154      break;
155
156#ifdef OSL_GMP_IS_HERE
157    case OSL_PRECISION_MP:
158      mpz_init(*(mpz_t *)value);
159      break;
160#endif
161
162    default:
163      OSL_error("unknown precision");
164  }
165}
166
167
168void * osl_int_malloc(int precision) {
169  void * value;
170
171  switch (precision) {
172    case OSL_PRECISION_SP:
173      value = malloc(sizeof(long int));
174      break;
175
176    case OSL_PRECISION_DP:
177      value = malloc(sizeof(long long int));
178      *(long long int *)value = 0;
179      break;
180
181#ifdef OSL_GMP_IS_HERE
182    case OSL_PRECISION_MP:
183      value = malloc(sizeof(mpz_t));
184      break;
185#endif
186
187    default:
188      OSL_error("unknown precision");
189  }
190
191  osl_int_init(precision, value, 0);
192  return value;
193}
194
195
196/**
197 * val1_base[val1_offset] = val2_base[val2_offset];
198 */
199void osl_int_assign(int precision,
200                    void * val1_base, int val1_offset,
201                    void * val2_base, int val2_offset) {
202  void * val1 = osl_int_address(precision, val1_base, val1_offset);
203  void * val2 = osl_int_address(precision, val2_base, val2_offset);
204
205  switch (precision) {
206    case OSL_PRECISION_SP:
207      *(long int *)val1 = *(long int *)val2;
208      break;
209
210    case OSL_PRECISION_DP:
211      *(long long int *)val1 = *(long long int *)val2;
212      break;
213
214#ifdef OSL_GMP_IS_HERE
215    case OSL_PRECISION_MP:
216      mpz_set(*(mpz_t *)val1, *(mpz_t *)val2);
217      break;
218#endif
219
220    default:
221      OSL_error("unknown precision");
222  }
223}
224
225
226/**
227 * value_base[value_offset] = i;
228 */
229void osl_int_set_si(int precision, void * value_base, int value_offset,
230                    int i) {
231  void * value = osl_int_address(precision, value_base, value_offset);
232
233  switch (precision) {
234    case OSL_PRECISION_SP:
235      *(long int *)value = (long int)i;
236      break;
237
238    case OSL_PRECISION_DP:
239      *(long long int *)value = (long long int)i;
240      break;
241
242#ifdef OSL_GMP_IS_HERE
243    case OSL_PRECISION_MP:
244      mpz_set_si(*(mpz_t *)value, i);
245      break;
246#endif
247
248    default:
249      OSL_error("unknown precision");
250  }
251}
252
253
254/**
255 * return value_base[value_offset];
256 */
257int osl_int_get_si(int precision, void * value_base, int value_offset) {
258  void * value = osl_int_address(precision, value_base, value_offset);
259
260  switch (precision) {
261    case OSL_PRECISION_SP:
262      return *(int *)value;
263
264    case OSL_PRECISION_DP:
265      return *(int *)value;
266
267#ifdef OSL_GMP_IS_HERE
268    case OSL_PRECISION_MP:
269      return mpz_get_si(*(mpz_t *)value);
270#endif
271
272    default:
273      OSL_error("unknown precision");
274  }
275}
276
277
278/**
279 * value_base[value_offset] = i; // including initialization for GMP
280 */
281void osl_int_init_set_si(int precision,
282                         void * value_base, int value_offset, int i) {
283  void * value = osl_int_address(precision, value_base, value_offset);
284
285  switch (precision) {
286    case OSL_PRECISION_SP:
287      *(long int *)value = (long int)i;
288      break;
289
290    case OSL_PRECISION_DP:
291      *(long long int *)value = (long long int)i;
292      break;
293
294#ifdef OSL_GMP_IS_HERE
295    case OSL_PRECISION_MP:
296      mpz_init_set_si(*(mpz_t *)value, i);
297      break;
298#endif
299
300    default:
301      OSL_error("unknown precision");
302  }
303}
304
305
306/**
307 * value_base[value_offset] = 0; // Including cleaning for GMP
308 */
309void osl_int_clear(int precision, void * value_base, int value_offset) {
310  void * value = osl_int_address(precision, value_base, value_offset);
311
312  switch (precision) {
313    case OSL_PRECISION_SP:
314      *(long int *)value = 0;
315      break;
316
317    case OSL_PRECISION_DP:
318      *(long long int *)value = 0;
319      break;
320
321#ifdef OSL_GMP_IS_HERE
322    case OSL_PRECISION_MP:
323      mpz_clear(*(mpz_t *)value);
324      break;
325#endif
326
327    default:
328      OSL_error("unknown precision");
329  }
330}
331
332
333void osl_int_free(int precision, void * value_base, int value_offset) {
334  void * value = osl_int_address(precision, value_base, value_offset);
335
336  osl_int_clear(precision, value_base, value_offset);
337  free(value);
338}
339
340
341/**
342 * osl_int_print function:
343 * this function displays an integer value into a file (file, possibly stdout).
344 * \param file         The file where the integer has to be printed.
345 * \param precision    The precision of the integer.
346 * \param value_base   Address of the base integer value.
347 * \param value_offset Offset in number of values from the base integer value.
348 */
349void osl_int_print(FILE * file, int precision,
350                   void * value_base, int value_offset) {
351  char string[OSL_MAX_STRING];
352
353  osl_int_sprint(string, precision, value_base, value_offset);
354  fprintf(file, "%s", string);
355}
356
357
358/**
359 * osl_int_sprint function:
360 * this function prints an integer value into a string, it uses the
361 * OpenScop Library formats OSL_FMT_* to format the printing.
362 * \param string       The string where the integer has to be printed.
363 * \param precision    The precision of the integer.
364 * \param value_base   Address of the base integer value.
365 * \param value_offset Offset in number of values from the base integer value.
366 */
367void osl_int_sprint(char * string, int precision,
368                    void * value_base, int value_offset) {
369  void * value = osl_int_address(precision, value_base, value_offset);
370
371  switch (precision) {
372    case OSL_PRECISION_SP:
373      sprintf(string, OSL_FMT_SP, *(long int *)value);
374      break;
375
376    case OSL_PRECISION_DP:
377      sprintf(string, OSL_FMT_DP, *(long long int *)value);
378      break;
379
380#ifdef OSL_GMP_IS_HERE
381    case OSL_PRECISION_MP: {
382      char * str;
383      str = mpz_get_str(0, 10, *(mpz_t *)value); //TODO: 10 -> #define
384      sprintf(string, OSL_FMT_MP, str);
385      free(str);
386      break;
387    }
388#endif
389
390    default:
391      OSL_error("unknown precision");
392  }
393}
394
395
396/**
397 * osl_int_sprint_txt function:
398 * this function is similar to osl_int_sprintf but it prints the value
399 * using OSL_TMT_TXT_* formats.
400 * \see osl_int_sprintf
401 */
402void osl_int_sprint_txt(char * string, int precision,
403                        void * value_base, int value_offset) {
404  void * value = osl_int_address(precision, value_base, value_offset);
405
406  switch (precision) {
407    case OSL_PRECISION_SP:
408      sprintf(string, OSL_FMT_TXT_SP, *(long int *)value);
409      break;
410
411    case OSL_PRECISION_DP:
412      sprintf(string, OSL_FMT_TXT_DP, *(long long int *)value);
413      break;
414
415#ifdef OSL_GMP_IS_HERE
416    case OSL_PRECISION_MP: {
417      char * str;
418      str = mpz_get_str(0, 10, *(mpz_t *)value); //TODO: 10 -> #define
419      sprintf(string, OSL_FMT_TXT_MP, str);
420      free(str);
421      break;
422    }
423#endif
424
425    default:
426      OSL_error("unknown precision");
427  }
428}
429
430
431void osl_int_sread(char ** string, int precision,
432                   void * value_base, int value_offset) {
433  void * value = osl_int_address(precision, value_base, value_offset);
434  int nb_read = 0;
435
436  switch (precision) {
437    case OSL_PRECISION_SP:
438      nb_read = sscanf(*string, OSL_FMT_TXT_SP, (long int *)value);
439      if (nb_read == 0)
440        OSL_error("failed to read an integer");
441      break;
442
443    case OSL_PRECISION_DP:
444      nb_read = sscanf(*string, OSL_FMT_TXT_DP, (long long int *)value);
445      if (nb_read == 0)
446        OSL_error("failed to read an integer");
447      break;
448
449#ifdef OSL_GMP_IS_HERE
450    case OSL_PRECISION_MP: {
451      long long int tmp;
452      nb_read = sscanf(*string, OSL_FMT_TXT_DP, &tmp);
453      if (nb_read == 0)
454        OSL_error("failed to read an integer");
455      mpz_set_si(*(mpz_t *)value, tmp);
456      break;
457    }
458#endif
459
460    default:
461      OSL_error("unknown precision");
462  }
463
464  // Update the position in the input string.
465  *string = *string + nb_read;
466}
467
468
469/*+***************************************************************************
470 *                            Arithmetic Operations                          *
471 *****************************************************************************/
472
473
474/**
475 * result_base[result_offset] = value_base[value_offset] + 1;
476 */
477void osl_int_increment(int precision,
478                       void * result_base, int result_offset,
479                       void * value_base,  int value_offset) {
480  void * result = osl_int_address(precision, result_base, result_offset);
481  void * value  = osl_int_address(precision, value_base, value_offset);
482
483  switch (precision) {
484    case OSL_PRECISION_SP:
485      *(long int *)result = *(long int *)value + (long int)1;
486      break;
487
488    case OSL_PRECISION_DP:
489      *(long long int *)result = *(long long int *)value + (long long int)1;
490      break;
491
492#ifdef OSL_GMP_IS_HERE
493    case OSL_PRECISION_MP:
494      mpz_add_ui(*(mpz_t *)result, *(mpz_t *)value, 1);
495      break;
496#endif
497
498    default:
499      OSL_error("unknown precision");
500  }
501}
502
503
504/**
505 * result_base[result_offset] = value_base[value_offset] - 1;
506 */
507void osl_int_decrement(int precision,
508                       void * result_base, int result_offset,
509                       void * value_base,  int value_offset) {
510  void * result = osl_int_address(precision, result_base, result_offset);
511  void * value  = osl_int_address(precision, value_base, value_offset);
512
513  switch (precision) {
514    case OSL_PRECISION_SP:
515      *(long int *)result = *(long int *)value - (long int)1;
516      break;
517
518    case OSL_PRECISION_DP:
519      *(long long int *)result = *(long long int *)value - (long long int)1;
520      break;
521
522#ifdef OSL_GMP_IS_HERE
523    case OSL_PRECISION_MP: {
524      mpz_t one;
525      mpz_init_set_si(one, 1);
526      mpz_sub(*(mpz_t *)result, *(mpz_t *)value, one);
527      mpz_clear(one);
528      break;
529    }
530#endif
531
532    default:
533      OSL_error("unknown precision");
534  }
535}
536
537
538/**
539 * result_base[result_offset] = val1_base[val1_offset]+val2_base[val2_offset];
540 */
541void osl_int_add(int precision,
542                 void * result_base, int result_offset,
543                 void * val1_base,   int val1_offset,
544                 void * val2_base,   int val2_offset) {
545  void * result = osl_int_address(precision, result_base, result_offset);
546  void * val1   = osl_int_address(precision, val1_base, val1_offset);
547  void * val2   = osl_int_address(precision, val2_base, val2_offset);
548
549  switch (precision) {
550    case OSL_PRECISION_SP:
551      *(long int *)result = *(long int *)val1 + *(long int *)val2;
552      break;
553
554    case OSL_PRECISION_DP:
555      *(long long int *)result = *(long long int *)val1 +
556                                 *(long long int *)val2;
557      break;
558
559#ifdef OSL_GMP_IS_HERE
560    case OSL_PRECISION_MP:
561      mpz_add(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
562      break;
563#endif
564
565    default:
566      OSL_error("unknown precision");
567  }
568}
569
570
571/**
572 * result_base[result_offset] = value_base[value_offset] + i;
573 */
574void osl_int_add_si(int precision,
575                    void * result_base, int result_offset,
576                    void * value_base,  int value_offset, int i) {
577  void * result = osl_int_address(precision, result_base, result_offset);
578  void * value  = osl_int_address(precision, value_base, value_offset);
579
580  switch (precision) {
581    case OSL_PRECISION_SP:
582      *(long int *)result = *(long int *)value + (long int)i;
583      break;
584
585    case OSL_PRECISION_DP:
586      *(long long int *)result = *(long long int *)value + (long long int)i;
587      break;
588
589#ifdef OSL_GMP_IS_HERE
590    case OSL_PRECISION_MP: {
591      mpz_t si;
592      mpz_init_set_si(si, i);
593      mpz_add(*(mpz_t *)result, *(mpz_t *)value, si);
594      mpz_clear(si);
595      break;
596    }
597#endif
598
599    default:
600      OSL_error("unknown precision");
601  }
602}
603
604
605/**
606 * result_base[result_offset] = val1_base[val1_offset]*val2_base[val2_offset];
607 */
608void osl_int_mul(int precision,
609                 void * result_base, int result_offset,
610                 void * val1_base,   int val1_offset,
611                 void * val2_base,   int val2_offset) {
612  void * result = osl_int_address(precision, result_base, result_offset);
613  void * val1   = osl_int_address(precision, val1_base, val1_offset);
614  void * val2   = osl_int_address(precision, val2_base, val2_offset);
615
616  switch (precision) {
617    case OSL_PRECISION_SP:
618      *(long int *)result = *(long int *)val1 * *(long int *)val2;
619      break;
620
621    case OSL_PRECISION_DP:
622      *(long long int *)result = *(long long int *)val1 *
623                                 *(long long int *)val2;
624      break;
625
626#ifdef OSL_GMP_IS_HERE
627    case OSL_PRECISION_MP:
628      mpz_mul(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
629      break;
630#endif
631
632    default:
633      OSL_error("unknown precision");
634  }
635}
636
637
638/**
639 * result_base[result_offset] = value_base[value_offset] * i;
640 */
641void osl_int_mul_si(int precision,
642                    void * result_base, int result_offset,
643                    void * value_base,  int value_offset, int i) {
644  void * result = osl_int_address(precision, result_base, result_offset);
645  void * value  = osl_int_address(precision, value_base, value_offset);
646
647  switch (precision) {
648    case OSL_PRECISION_SP:
649      *(long int *)result = *(long int *)value * (long int)i;
650      break;
651
652    case OSL_PRECISION_DP:
653      *(long long int *)result = *(long long int *)value * (long long int)i;
654      break;
655
656#ifdef OSL_GMP_IS_HERE
657    case OSL_PRECISION_MP:
658      mpz_mul_si(*(mpz_t *)result, *(mpz_t *)value, i);
659      break;
660#endif
661
662    default:
663      OSL_error("unknown precision");
664  }
665}
666
667
668/**
669 * result_base[result_offset] = val1_base[val1_offset]-val2_base[val2_offset];
670 */
671void osl_int_sub(int precision,
672                 void * result_base, int result_offset,
673                 void * val1_base,   int val1_offset,
674                 void * val2_base,   int val2_offset) {
675  void * result = osl_int_address(precision, result_base, result_offset);
676  void * val1   = osl_int_address(precision, val1_base, val1_offset);
677  void * val2   = osl_int_address(precision, val2_base, val2_offset);
678
679  switch (precision) {
680    case OSL_PRECISION_SP:
681      *(long int *)result = *(long int *)val1 - *(long int *)val2;
682      break;
683
684    case OSL_PRECISION_DP:
685      *(long long int *)result = *(long long int *)val1 -
686                                 *(long long int *)val2;
687      break;
688
689#ifdef OSL_GMP_IS_HERE
690    case OSL_PRECISION_MP:
691      mpz_sub(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
692      break;
693#endif
694
695    default:
696      OSL_error("unknown precision");
697  }
698}
699
700
701/**
702 * result_base[result_offset] = -value_base[value_offset];
703 */
704void osl_int_oppose(int precision,
705                    void * result_base, int result_offset,
706                    void * value_base,  int value_offset) {
707  void * result = osl_int_address(precision, result_base, result_offset);
708  void * value  = osl_int_address(precision, value_base, value_offset);
709
710  switch (precision) {
711    case OSL_PRECISION_SP:
712      *(long int *)result = -*(long int *)value;
713      break;
714
715    case OSL_PRECISION_DP:
716      *(long long int *)result = -*(long long int *)value;
717      break;
718
719#ifdef OSL_GMP_IS_HERE
720    case OSL_PRECISION_MP:
721      mpz_neg(*(mpz_t *)result, *(mpz_t *)value);
722      break;
723#endif
724
725    default:
726      OSL_error("unknown precision");
727  }
728}
729
730
731/*+***************************************************************************
732 *                            Conditional Operations                         *
733 *****************************************************************************/
734
735
736/**
737 * (val1_base[val1_offset] == val2_base[val2_offset])
738 */
739int osl_int_eq(int precision,
740               void * val1_base, int val1_offset,
741               void * val2_base, int val2_offset) {
742  void * val1 = osl_int_address(precision, val1_base, val1_offset);
743  void * val2 = osl_int_address(precision, val2_base, val2_offset);
744
745  switch (precision) {
746    case OSL_PRECISION_SP:
747      return (*(long int *)val1 == *(long int *)val2);
748
749    case OSL_PRECISION_DP:
750      return (*(long long int *)val1 == *(long long int *)val2);
751
752#ifdef OSL_GMP_IS_HERE
753    case OSL_PRECISION_MP:
754      return (mpz_cmp(*(mpz_t *)val1, *(mpz_t *)val2) == 0);
755#endif
756
757    default:
758      OSL_error("unknown precision");
759  }
760}
761
762
763/**
764 * (val1_base[val1_offset] != val2_base[val2_offset])
765 */
766int osl_int_ne(int precision,
767               void * val1_base, int val1_offset,
768               void * val2_base, int val2_offset) {
769  return !osl_int_eq(precision,
770                          val1_base, val1_offset,
771                          val2_base, val2_offset);
772}
773
774
775/**
776 * (value_base[value_offset] > 0)
777 */
778int osl_int_pos(int precision, void * value_base, int value_offset) {
779  void * value = osl_int_address(precision, value_base, value_offset);
780
781  switch (precision) {
782    case OSL_PRECISION_SP:
783      return (*(long int *)value > 0);
784
785    case OSL_PRECISION_DP:
786      return (*(long long int *)value > 0);
787
788#ifdef OSL_GMP_IS_HERE
789    case OSL_PRECISION_MP:
790      return (mpz_sgn(*(mpz_t *)value) > 0);
791#endif
792
793    default:
794      OSL_error("unknown precision");
795  }
796}
797
798
799/**
800 * (value_base[value_offset] < 0)
801 */
802int osl_int_neg(int precision, void * value_base, int value_offset) {
803  void * value = osl_int_address(precision, value_base, value_offset);
804
805  switch (precision) {
806    case OSL_PRECISION_SP:
807      return (*(long int *)value < 0);
808
809    case OSL_PRECISION_DP:
810      return (*(long long int *)value < 0);
811
812#ifdef OSL_GMP_IS_HERE
813    case OSL_PRECISION_MP:
814      return (mpz_sgn(*(mpz_t *)value) < 0);
815#endif
816
817    default:
818      OSL_error("unknown precision");
819  }
820}
821
822
823/**
824 * (value_base[value_offset] == 0)
825 */
826int osl_int_zero(int precision, void * value_base, int value_offset) {
827  void * value = osl_int_address(precision, value_base, value_offset);
828
829  switch (precision) {
830    case OSL_PRECISION_SP:
831      return (*(long int *)value == 0);
832
833    case OSL_PRECISION_DP:
834      return (*(long long int *)value == 0);
835
836#ifdef OSL_GMP_IS_HERE
837    case OSL_PRECISION_MP:
838      return (mpz_sgn(*(mpz_t *)value) == 0);
839#endif
840
841    default:
842      OSL_error("unknown precision");
843  }
844}
845
846
847/**
848 * (value_base[value_offset] == 1)
849 */
850int osl_int_one(int precision, void * value_base, int value_offset) {
851  void * value = osl_int_address(precision, value_base, value_offset);
852
853  switch (precision) {
854    case OSL_PRECISION_SP:
855      return (*(long int *)value == (long int)1);
856
857    case OSL_PRECISION_DP:
858      return (*(long long int *)value == (long long int)1);
859
860#ifdef OSL_GMP_IS_HERE
861    case OSL_PRECISION_MP:
862      return (mpz_cmp_si(*(mpz_t *)value, 1) == 0);
863#endif
864
865    default:
866      OSL_error("unknown precision");
867  }
868}
869
870
871/**
872 * (value_base[value_offset] == -1)
873 */
874int osl_int_mone(int precision, void * value_base, int value_offset) {
875  void * value = osl_int_address(precision, value_base, value_offset);
876
877  switch (precision) {
878    case OSL_PRECISION_SP:
879      return (*(long int *)value == (long int)-1);
880
881    case OSL_PRECISION_DP:
882      return (*(long long int *)value == (long long int)-1);
883
884#ifdef OSL_GMP_IS_HERE
885    case OSL_PRECISION_MP:
886      return (mpz_cmp_si(*(mpz_t *)value, -1) == 0);
887#endif
888
889    default:
890      OSL_error("unknown precision");
891  }
892}
893
894
895/**
896 * ((val1_base[val1_offset] % val2_base[val2_offset]) == 0)
897 */
898int osl_int_divisible(int precision,
899                      void * val1_base, int val1_offset,
900                      void * val2_base, int val2_offset) {
901  void * val1 = osl_int_address(precision, val1_base, val1_offset);
902  void * val2 = osl_int_address(precision, val2_base, val2_offset);
903
904  switch (precision) {
905    case OSL_PRECISION_SP:
906      return ((*(long int *)val1 % *(long int *)val2) == 0);
907
908    case OSL_PRECISION_DP:
909      return ((*(long long int *)val1 % *(long long int *)val2) == 0);
910
911#ifdef OSL_GMP_IS_HERE
912    case OSL_PRECISION_MP:
913      return mpz_divisible_p(*(mpz_t *)val1, *(mpz_t *)val2);
914#endif
915
916    default:
917      OSL_error("unknown precision");
918  }
919}
920