OpenScop  0.9.0
int.c
Go to the documentation of this file.
00001 
00002     /*+-----------------------------------------------------------------**
00003      **                       OpenScop Library                          **
00004      **-----------------------------------------------------------------**
00005      **                             int.c                               **
00006      **-----------------------------------------------------------------**
00007      **                   First version: 18/07/2011                     **
00008      **-----------------------------------------------------------------**
00009 
00010  
00011  *****************************************************************************
00012  * OpenScop: Structures and formats for polyhedral tools to talk together    *
00013  *****************************************************************************
00014  *    ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__,                *
00015  *    /   / /  //  //  //  // /   / /  //  //   / /  // /  /|,_,             *
00016  *   /   / /  //  //  //  // /   / /  //  //   / /  // /  / / /\             *
00017  *  |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/  \            *
00018  *  | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\  \ /\           *
00019  *  | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\          *
00020  *  | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \  \         *
00021  *  | P |n| l | = | s | t |=| = |d| = | = | = | |   |=| o | | \# \  \        *
00022  *  | H | | y |   | e | o | | = |l|   |   | = | |   | | G | |  \  \  \       *
00023  *  | I | |   |   | e |   | |   | |   |   |   | |   | |   | |   \  \  \      *
00024  *  | T | |   |   |   |   | |   | |   |   |   | |   | |   | |    \  \  \     *
00025  *  | E | |   |   |   |   | |   | |   |   |   | |   | |   | |     \  \  \    *
00026  *  | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | /      \* \  \   *
00027  *  | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/        \  \ /   *
00028  *  '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---'          '--'    *
00029  *                                                                           *
00030  * Copyright (C) 2008 University Paris-Sud 11 and INRIA                      *
00031  *                                                                           *
00032  * (3-clause BSD license)                                                    *
00033  * Redistribution and use in source  and binary forms, with or without       *
00034  * modification, are permitted provided that the following conditions        *
00035  * are met:                                                                  *
00036  *                                                                           *
00037  * 1. Redistributions of source code must retain the above copyright notice, *
00038  *    this list of conditions and the following disclaimer.                  *
00039  * 2. Redistributions in binary form must reproduce the above copyright      *
00040  *    notice, this list of conditions and the following disclaimer in the    *
00041  *    documentation and/or other materials provided with the distribution.   *
00042  * 3. The name of the author may not be used to endorse or promote products  *
00043  *    derived from this software without specific prior written permission.  *
00044  *                                                                           *
00045  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      *
00046  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
00047  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   *
00048  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          *
00049  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  *
00050  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
00051  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     *
00052  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
00053  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  *
00054  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         *
00055  *                                                                           *
00056  * OpenScop Library, a library to manipulate OpenScop formats and data       *
00057  * structures. Written by:                                                   *
00058  * Cedric Bastoul     <Cedric.Bastoul@u-psud.fr> and                         *
00059  * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr>                          *
00060  *                                                                           *
00061  *****************************************************************************/
00062 
00063 #include <stdlib.h>
00064 #include <stdio.h>
00065 #include <limits.h>
00066 
00067 #ifdef OSL_GMP_IS_HERE
00068 # include <gmp.h>
00069 #endif
00070 
00071 #include <osl/macros.h>
00072 #include <osl/int.h>
00073 
00074 
00075 /*+***************************************************************************
00076  *                                Basic Functions                            *
00077  *****************************************************************************/
00078 
00079 
00090 int osl_int_is_precision_supported(int precision) {
00091   switch (precision) {
00092     case OSL_PRECISION_SP:
00093       return 1;
00094     case OSL_PRECISION_DP:
00095       return 1;
00096 #ifdef OSL_GMP_IS_HERE
00097     case OSL_PRECISION_MP:
00098       return 1;
00099 #endif
00100   }
00101 
00102   return 0;
00103 }
00104 
00105 
00113 void osl_int_dump_precision(FILE * file, int precision) {
00114   switch (precision) {
00115     case OSL_PRECISION_SP:
00116       fprintf(file, "32 bits");
00117       break;
00118     case OSL_PRECISION_DP:
00119       fprintf(file, "64 bits");
00120       break;
00121 #ifdef OSL_GMP_IS_HERE
00122     case OSL_PRECISION_MP:
00123       fprintf(file, "GMP");
00124       break;
00125 #endif
00126     default:
00127       fprintf(file, "unknown precision %d", precision);
00128   }
00129 }
00130 
00131 
00132 void osl_int_init(int precision, osl_int_const_p variable) {
00133   switch (precision) {
00134     case OSL_PRECISION_SP:
00135       variable->sp = 0;
00136       break;
00137 
00138     case OSL_PRECISION_DP:
00139       variable->dp = 0;
00140       break;
00141 
00142 #ifdef OSL_GMP_IS_HERE
00143     case OSL_PRECISION_MP:
00144       OSL_malloc(variable->mp, void*, sizeof(mpz_t)); 
00145       mpz_init(*variable->mp);
00146       break;
00147 #endif
00148 
00149     default:
00150       OSL_error("unknown precision");
00151   }
00152 }
00153 
00154 
00155 osl_int_p osl_int_malloc(int precision) {
00156   osl_int_p variable;
00157 
00158   OSL_malloc(variable, osl_int_p, sizeof(osl_int_t));
00159   osl_int_init(precision, variable);
00160   return variable;
00161 }
00162 
00163 
00167 void osl_int_assign(int precision,
00168                     osl_int_const_p variable, osl_const_int_t value) {
00169   switch (precision) {
00170     case OSL_PRECISION_SP:
00171       variable->sp = value.sp;
00172       break;
00173 
00174     case OSL_PRECISION_DP:
00175       variable->dp = value.dp;
00176       break;
00177 
00178 #ifdef OSL_GMP_IS_HERE
00179     case OSL_PRECISION_MP:
00180       mpz_set(*variable->mp, *value.mp);
00181       break;
00182 #endif
00183 
00184     default:
00185       OSL_error("unknown precision");
00186   }
00187 }
00188 
00189 
00193 void osl_int_set_si(int precision, osl_int_const_p variable, int i) {
00194   switch (precision) {
00195     case OSL_PRECISION_SP:
00196       variable->sp = (long int)i;
00197       break;
00198 
00199     case OSL_PRECISION_DP:
00200       variable->dp = (long long int)i;
00201       break;
00202 
00203 #ifdef OSL_GMP_IS_HERE
00204     case OSL_PRECISION_MP:
00205       mpz_set_si(*variable->mp, i);
00206       break;
00207 #endif
00208 
00209     default:
00210       OSL_error("unknown precision");
00211   }
00212 }
00213 
00214 
00218 int osl_int_get_si(int precision, osl_const_int_t value) {
00219   switch (precision) {
00220     case OSL_PRECISION_SP:
00221       #ifndef NDEBUG
00222         if (value.sp > (long int)(INT_MAX))
00223           OSL_overflow("osl_int_get_si overflow");
00224         if (value.sp < (long int)(INT_MIN))
00225           OSL_overflow("osl_int_get_si overflow");
00226       #endif
00227       return (int)value.sp;
00228 
00229     case OSL_PRECISION_DP:
00230       #ifndef NDEBUG
00231         if (value.dp > (long long int)(INT_MAX))
00232           OSL_overflow("osl_int_get_si overflow");
00233         if (value.dp < (long long int)(INT_MIN))
00234           OSL_overflow("osl_int_get_si overflow");
00235       #endif
00236       return (int)value.dp;
00237 
00238 #ifdef OSL_GMP_IS_HERE
00239     case OSL_PRECISION_MP:
00240       #ifndef NDEBUG
00241         if (mpz_fits_sint_p(*value.mp) == 0)
00242           OSL_overflow("osl_int_get_si overflow");
00243       #endif
00244       return mpz_get_si(*value.mp);
00245 #endif
00246 
00247     default:
00248       OSL_error("unknown precision");
00249   }
00250 }
00251 
00252 
00259 double osl_int_get_d(int precision, osl_const_int_t i) {
00260   switch (precision) {
00261     case OSL_PRECISION_SP:
00262       return (double)i.sp;
00263 
00264     case OSL_PRECISION_DP:
00265       return (double)i.dp;
00266 
00267 #ifdef OSL_GMP_IS_HERE
00268     case OSL_PRECISION_MP:
00269       return mpz_get_d(*i.mp);
00270 #endif
00271 
00272     default:
00273       OSL_error("unknown precision");
00274   }
00275 }
00276 
00277 
00281 void osl_int_init_set(int precision, osl_int_const_p variable, osl_const_int_t i) {
00282   osl_int_init(precision, variable);
00283   osl_int_assign(precision, variable, i);
00284 }
00285 
00286 
00290 void osl_int_init_set_si(int precision, osl_int_const_p variable, int i) {
00291   switch (precision) {
00292     case OSL_PRECISION_SP:
00293       variable->sp = (long int)i;
00294       break;
00295 
00296     case OSL_PRECISION_DP:
00297       variable->dp = (long long int)i;
00298       break;
00299 
00300 #ifdef OSL_GMP_IS_HERE
00301     case OSL_PRECISION_MP:
00302       OSL_malloc(variable->mp, void*, sizeof(mpz_t)); 
00303       mpz_init_set_si(*variable->mp, i);
00304       break;
00305 #endif
00306 
00307     default:
00308       OSL_error("unknown precision");
00309   }
00310 }
00311 
00312 
00316 void osl_int_swap(int precision, osl_int_const_p var1, osl_int_const_p var2) {
00317   switch (precision) {
00318     case OSL_PRECISION_SP: {
00319       long int temp = var1->sp;
00320       var1->sp = var2->sp;
00321       var2->sp = temp;
00322       break;
00323     }
00324 
00325     case OSL_PRECISION_DP: {
00326       long long int temp = var1->dp;
00327       var1->dp = var2->dp;
00328       var2->dp = temp;
00329       break;
00330     }
00331 
00332 #ifdef OSL_GMP_IS_HERE
00333     case OSL_PRECISION_MP: {
00334       mpz_t temp;
00335       mpz_init(temp);
00336       mpz_set(temp, *var1->mp);
00337       mpz_set(*var1->mp, *var2->mp);
00338       mpz_set(*var2->mp, temp);
00339       mpz_clear(temp);
00340       break;
00341     }
00342 #endif
00343 
00344     default:
00345       OSL_error("unknown precision");
00346   }
00347 }
00348 
00349 
00353 void osl_int_clear(int precision, osl_int_const_p variable) {
00354   switch (precision) {
00355     case OSL_PRECISION_SP:
00356       variable->sp = 0;
00357       break;
00358 
00359     case OSL_PRECISION_DP:
00360       variable->dp = 0;
00361       break;
00362 
00363 #ifdef OSL_GMP_IS_HERE
00364     case OSL_PRECISION_MP:
00365       mpz_clear(*variable->mp);
00366       free(variable->mp);
00367       break;
00368 #endif
00369 
00370     default:
00371       OSL_error("unknown precision");
00372   }
00373 }
00374 
00375 
00376 void osl_int_free(int precision, osl_int_const_p variable) {
00377   osl_int_clear(precision, variable);
00378   free(variable);
00379 }
00380 
00381 
00389 void osl_int_print(FILE * file, int precision, osl_const_int_t value) {
00390   char string[OSL_MAX_STRING];
00391   
00392   osl_int_sprint(string, precision, value);
00393   fprintf(file, "%s", string);
00394 }
00395 
00396 
00405 void osl_int_sprint(char * string, int precision, osl_const_int_t value) {
00406   switch (precision) {
00407     case OSL_PRECISION_SP:
00408       sprintf(string, OSL_FMT_SP, value.sp);
00409       break;
00410 
00411     case OSL_PRECISION_DP:
00412       sprintf(string, OSL_FMT_DP, value.dp);
00413       break;
00414 
00415 #ifdef OSL_GMP_IS_HERE
00416     case OSL_PRECISION_MP: {
00417       char * str;
00418       str = mpz_get_str(0, 10, *value.mp); //TODO: 10 -> #define
00419       sprintf(string, OSL_FMT_MP, str);
00420       free(str);
00421       break;
00422     }
00423 #endif
00424 
00425     default:
00426       OSL_error("unknown precision");
00427   }
00428 }
00429 
00430 
00437 void osl_int_sprint_txt(char * string, int precision, osl_const_int_t value) {
00438   switch (precision) {
00439     case OSL_PRECISION_SP:
00440       sprintf(string, OSL_FMT_TXT_SP, value.sp);
00441       break;
00442 
00443     case OSL_PRECISION_DP:
00444       sprintf(string, OSL_FMT_TXT_DP, value.dp);
00445       break;
00446 
00447 #ifdef OSL_GMP_IS_HERE
00448     case OSL_PRECISION_MP: {
00449       char * str;
00450       str = mpz_get_str(0, 10, *value.mp); //TODO: 10 -> #define
00451       sprintf(string, OSL_FMT_TXT_MP, str);
00452       free(str);
00453       break;
00454     }
00455 #endif
00456 
00457     default:
00458       OSL_error("unknown precision");
00459   }
00460 }
00461 
00462 
00463 int osl_int_sscanf(char* string, int precision, osl_int_const_p i) {
00464   int nb_read = 0;
00465 
00466   switch (precision) {
00467     case OSL_PRECISION_SP:
00468       nb_read = sscanf(string, OSL_FMT_TXT_SP, &(i->sp));
00469       break;
00470 
00471     case OSL_PRECISION_DP:
00472       nb_read = sscanf(string, OSL_FMT_TXT_DP, &(i->dp));
00473       break;
00474 
00475 #ifdef OSL_GMP_IS_HERE
00476     case OSL_PRECISION_MP: {
00477       nb_read = gmp_sscanf(string, "%lZd", i->mp);
00478       break;
00479     }
00480 #endif
00481 
00482     default:
00483       OSL_error("unknown precision");
00484   }
00485   
00486   if (nb_read == 0) { OSL_error("failed to read an integer"); }
00487 
00488   return nb_read;
00489 }
00490 
00491 
00492 void osl_int_sread(char ** string, int precision, osl_int_const_p i) {
00493   // Update the position in the input string.
00494   *string += osl_int_sscanf(*string, precision, i);
00495 }
00496 
00497 
00498 /*+***************************************************************************
00499  *                            Arithmetic Operations                          *
00500  *****************************************************************************/
00501 
00502 
00506 void osl_int_increment(int precision,
00507                        osl_int_const_p variable, osl_const_int_t value) {
00508   osl_int_add_si(precision, variable, value, 1);
00509 }
00510 
00511 
00515 void osl_int_decrement(int precision,
00516                        osl_int_const_p variable, osl_const_int_t value) {
00517   osl_int_add_si(precision, variable, value, -1);
00518 }
00519 
00520 
00524 void osl_int_add(int precision, osl_int_const_p variable,
00525                  osl_const_int_t val1, osl_const_int_t val2) {
00526   switch (precision) {
00527     case OSL_PRECISION_SP:
00528       #ifndef NDEBUG
00529         if (osl_int_pos(precision, val1) && osl_int_pos(precision, val2)) {
00530           if (LONG_MAX - val1.sp < val2.sp)
00531             OSL_overflow("osl_int_add overflow");
00532         }
00533         else if (osl_int_neg(precision, val1) && osl_int_neg(precision, val2)) {
00534           if (val1.sp - LONG_MIN < -val2.sp)
00535             OSL_overflow("osl_int_add overflow");
00536         }
00537       #endif
00538       variable->sp = val1.sp + val2.sp;
00539       break;
00540 
00541     case OSL_PRECISION_DP:
00542       #ifndef NDEBUG
00543         if (osl_int_pos(precision, val1) && osl_int_pos(precision, val2)) {
00544           if (LLONG_MAX - val1.dp < val2.dp)
00545             OSL_overflow("osl_int_add overflow");
00546         }
00547         else if (osl_int_neg(precision, val1) && osl_int_neg(precision, val2)) {
00548           if (val1.dp - LLONG_MIN < -val2.dp)
00549             OSL_overflow("osl_int_add overflow");
00550         }
00551       #endif
00552       variable->dp = val1.dp + val2.dp;
00553       break;
00554 
00555 #ifdef OSL_GMP_IS_HERE
00556     case OSL_PRECISION_MP:
00557       mpz_add(*variable->mp, *val1.mp, *val2.mp);
00558       break;
00559 #endif
00560 
00561     default:
00562       OSL_error("unknown precision");
00563   }
00564 }
00565 
00566 
00570 void osl_int_add_si(int precision,
00571                     osl_int_const_p variable, osl_const_int_t value, int i) {
00572   switch (precision) {
00573     case OSL_PRECISION_SP:
00574       #ifndef NDEBUG
00575         if (osl_int_pos(precision, value) && i > 0) {
00576           if (LONG_MAX - value.sp < i)
00577             OSL_overflow("osl_int_add_si overflow");
00578         }
00579         else if (osl_int_neg(precision, value) && i < 0) {
00580           if (value.sp - LONG_MIN < -i)
00581             OSL_overflow("osl_int_add_si overflow");
00582         }
00583       #endif
00584       variable->sp = value.sp + (long int)i;
00585       break;
00586 
00587     case OSL_PRECISION_DP:
00588       #ifndef NDEBUG
00589         if (osl_int_pos(precision, value) && i > 0) {
00590           if (LLONG_MAX - value.dp < i)
00591             OSL_overflow("osl_int_add_si overflow");
00592         }
00593         else if (osl_int_neg(precision, value) && i < 0) {
00594           if (value.dp - LLONG_MIN < -i)
00595             OSL_overflow("osl_int_add_si overflow");
00596         }
00597       #endif
00598       variable->dp = value.dp + (long long int)i;
00599       break;
00600 
00601 #ifdef OSL_GMP_IS_HERE
00602     case OSL_PRECISION_MP: {
00603       mpz_t si;
00604       mpz_init_set_si(si, i);
00605       mpz_add(*variable->mp, *value.mp, si);
00606       mpz_clear(si);
00607       break;
00608     }
00609 #endif
00610 
00611     default:
00612       OSL_error("unknown precision");
00613   }
00614 }
00615 
00616 
00620 void osl_int_sub(int precision, osl_int_const_p variable,
00621                  osl_const_int_t val1, osl_const_int_t val2) {
00622 #ifdef OSL_GMP_IS_HERE
00623   if (precision == OSL_PRECISION_MP) {
00624     mpz_sub(*variable->mp, *val1.mp, *val2.mp);
00625   }
00626   else
00627 #endif
00628   {
00629     osl_int_t mval2; osl_int_init(precision, &mval2);
00630     osl_int_oppose(precision, &mval2, val2);
00631     osl_int_add(precision, variable, val1, mval2);
00632   }
00633 }
00634 
00635 
00639 void osl_int_mul(int precision, osl_int_const_p variable,
00640                  osl_const_int_t val1, osl_const_int_t val2) {
00641   switch (precision) {
00642     case OSL_PRECISION_SP:
00643       variable->sp = val1.sp * val2.sp;
00644       #ifndef NDEBUG
00645         if (!osl_int_zero(precision, val1) && !osl_int_zero(precision, val2)) {
00646           if (variable->sp / val2.sp != val1.sp) {
00647             OSL_overflow("osl_int_mul overflow");
00648           }
00649         }
00650       #endif
00651       break;
00652 
00653     case OSL_PRECISION_DP:
00654       variable->dp = val1.dp * val2.dp;
00655       #ifndef NDEBUG
00656         if (!osl_int_zero(precision, val1) && !osl_int_zero(precision, val2)) {
00657           if (variable->dp / val2.dp != val1.dp) {
00658             OSL_overflow("osl_int_mul overflow");
00659           }
00660         }
00661       #endif
00662       break;
00663 
00664 #ifdef OSL_GMP_IS_HERE
00665     case OSL_PRECISION_MP:
00666       mpz_mul(*variable->mp, *val1.mp, *val2.mp);
00667       break;
00668 #endif
00669 
00670     default:
00671       OSL_error("unknown precision");
00672   }
00673 }
00674 
00675 
00679 void osl_int_mul_si(int precision,
00680                     osl_int_const_p variable, osl_const_int_t value, int i) {
00681   switch (precision) {
00682     case OSL_PRECISION_SP:
00683       variable->sp = value.sp * (long int)i;
00684       #ifndef NDEBUG
00685         if (!osl_int_zero(precision, value) && i != 0) {
00686           if (variable->sp / (long int)i != value.sp) {
00687             OSL_overflow("osl_int_mul_si overflow");
00688           }
00689         }
00690       #endif
00691       break;
00692 
00693     case OSL_PRECISION_DP:
00694       variable->dp = value.dp * (long long int)i;
00695       #ifndef NDEBUG
00696         if (!osl_int_zero(precision, value) && i != 0) {
00697           if (variable->dp / (long long int)i != value.dp) {
00698             OSL_overflow("osl_int_mul_si overflow");
00699           }
00700         }
00701       #endif
00702       break;
00703 
00704 #ifdef OSL_GMP_IS_HERE
00705     case OSL_PRECISION_MP:
00706       mpz_mul_si(*variable->mp, *value.mp, i);
00707       break;
00708 #endif
00709 
00710     default:
00711       OSL_error("unknown precision");
00712   }
00713 }
00714 
00715 
00720 void osl_int_div_exact(int const precision,
00721                        osl_int_const_p q,
00722                        osl_const_int_t a, osl_const_int_t b) {
00723   switch (precision) {
00724     case OSL_PRECISION_SP: q->sp = a.sp / b.sp; return;
00725 
00726     case OSL_PRECISION_DP: q->dp = a.dp / b.dp; return;
00727 
00728 #ifdef OSL_GMP_IS_HERE
00729     case OSL_PRECISION_MP: mpz_divexact(*q->mp, *a.mp, *b.mp); return;
00730 #endif
00731 
00732     default: OSL_error("unknown precision");
00733   }
00734 }
00735 
00736 
00742 void osl_int_floor_div_q(int const precision,
00743                          osl_int_const_p q,
00744                          osl_const_int_t a, osl_const_int_t b) {
00745   switch (precision) {
00746     case OSL_PRECISION_SP:
00747       q->sp = a.sp / b.sp;
00748       if (q->sp < 0) { if (a.sp % b.sp != 0) --q->sp; }
00749       else if (q->sp == 0) {
00750         if ((osl_int_pos(precision, a) && osl_int_neg(precision, b)) ||
00751             (osl_int_neg(precision, a) && osl_int_pos(precision, b))) {
00752           --q->sp;
00753         }
00754       }
00755       return;
00756 
00757     case OSL_PRECISION_DP:
00758       q->dp = a.dp / b.dp;
00759       if (q->dp < 0) { if (a.dp % b.dp != 0) --q->dp; }
00760       else if (q->dp == 0) {
00761         if ((osl_int_pos(precision, a) && osl_int_neg(precision, b)) ||
00762             (osl_int_neg(precision, a) && osl_int_pos(precision, b))) {
00763           --q->dp;
00764         }
00765       }
00766       return;
00767 
00768 #ifdef OSL_GMP_IS_HERE
00769     case OSL_PRECISION_MP: mpz_fdiv_q(*q->mp, *a.mp, *b.mp); return;
00770 #endif
00771 
00772     default: OSL_error("unknown precision");
00773   }
00774 }
00775 
00776 
00782 void osl_int_floor_div_r(int const precision,
00783                          osl_int_const_p r,
00784                          osl_const_int_t a, osl_const_int_t b) {
00785   switch (precision) {
00786     case OSL_PRECISION_SP:
00787       osl_int_floor_div_q(precision, r, a, b);
00788       r->sp = a.sp - r->sp * b.sp;
00789       return;
00790 
00791     case OSL_PRECISION_DP:
00792       osl_int_floor_div_q(precision, r, a, b);
00793       r->dp = a.dp - r->dp * b.dp;
00794       return;
00795 
00796 #ifdef OSL_GMP_IS_HERE
00797     case OSL_PRECISION_MP: mpz_fdiv_r(*r->mp, *a.mp, *b.mp); return;
00798 #endif
00799 
00800     default: OSL_error("unknown precision");
00801   }
00802 }
00803 
00804 
00811 void osl_int_floor_div_q_r(int const precision,
00812                            osl_int_const_p q, osl_int_const_p r,
00813                            osl_const_int_t a, osl_const_int_t b) {
00814   switch (precision) {
00815     case OSL_PRECISION_SP:
00816       osl_int_floor_div_q(precision, q, a, b);
00817       r->sp = a.sp - q->sp * b.sp;
00818       return;
00819 
00820     case OSL_PRECISION_DP:
00821       osl_int_floor_div_q(precision, q, a, b);
00822       r->dp = a.dp - q->dp * b.dp;
00823       return;
00824 
00825 #ifdef OSL_GMP_IS_HERE
00826     case OSL_PRECISION_MP: mpz_fdiv_qr(*q->mp, *r->mp, *a.mp, *b.mp); return;
00827 #endif
00828 
00829     default: OSL_error("unknown precision");
00830   }
00831 }
00832 
00833 
00839 void osl_int_mod(int const precision, osl_int_const_p mod,
00840                                       osl_const_int_t a, osl_const_int_t b) {
00841   switch (precision) {
00842     case OSL_PRECISION_SP:
00843       mod->sp = a.sp % b.sp;
00844       if (mod->sp < 0) mod->sp += labs(b.sp);
00845       return;
00846 
00847     case OSL_PRECISION_DP:
00848       mod->dp = a.dp % b.dp;
00849       if (mod->dp < 0) mod->dp += llabs(b.dp);
00850       return;
00851 
00852 #ifdef OSL_GMP_IS_HERE
00853     case OSL_PRECISION_MP: mpz_mod(*mod->mp, *a.mp, *b.mp); return;
00854 #endif
00855 
00856     default: OSL_error("unknown precision");
00857   }
00858 }
00859 
00860 
00861 // gcd (greatest common divisor) for long long int
00862 static long long int llgcd(long long int const a, long long int const b) {
00863   return (b ? llgcd(b, a % b) : a);
00864 }
00865 
00869 void osl_int_gcd(int const precision, osl_int_const_p gcd,
00870                                       osl_const_int_t a, osl_const_int_t b) {
00871   switch (precision) {
00872     case OSL_PRECISION_SP: gcd->sp = labs(llgcd(a.sp, b.sp)); return;
00873 
00874     case OSL_PRECISION_DP: gcd->dp = llabs(llgcd(a.dp, b.dp)); return;
00875 
00876 #ifdef OSL_GMP_IS_HERE
00877     case OSL_PRECISION_MP: mpz_gcd(*gcd->mp, *a.mp, *b.mp); return;
00878 #endif
00879 
00880     default: OSL_error("unknown precision");
00881   }
00882 }
00883 
00884 
00888 void osl_int_oppose(int precision,
00889                     osl_int_const_p variable, osl_const_int_t value) {
00890   switch (precision) {
00891     case OSL_PRECISION_SP:
00892       variable->sp = -value.sp;
00893       break;
00894 
00895     case OSL_PRECISION_DP:
00896       variable->dp = -value.dp;
00897       break;
00898 
00899 #ifdef OSL_GMP_IS_HERE
00900     case OSL_PRECISION_MP:
00901       mpz_neg(*variable->mp, *value.mp);
00902       break;
00903 #endif
00904 
00905     default:
00906       OSL_error("unknown precision");
00907   }
00908 }
00909 
00910 
00914 void osl_int_abs(int precision,
00915                  osl_int_const_p variable, osl_const_int_t value) {
00916   switch (precision) {
00917     case OSL_PRECISION_SP:
00918       variable->sp = (value.sp > 0) ? value.sp : -value.sp;
00919       break;
00920 
00921     case OSL_PRECISION_DP:
00922       variable->dp = (value.dp > 0) ? value.dp : -value.dp;
00923       break;
00924 
00925 #ifdef OSL_GMP_IS_HERE
00926     case OSL_PRECISION_MP:
00927       mpz_abs(*variable->mp, *value.mp);
00928       break;
00929 #endif
00930 
00931     default:
00932       OSL_error("unknown precision");
00933   }
00934 }
00935 
00936 
00937 // log2 function for long long int
00938 static size_t lllog2(long long int x) {
00939   size_t n = 0;
00940 
00941   x = llabs(x);
00942 
00943   while (x) { x >>= 1; ++n; }
00944 
00945   return ((n == 0) ? 1 : n);
00946 }
00947 
00951 size_t osl_int_size_in_base_2(int const precision,
00952                               osl_const_int_t const value) {
00953   switch (precision) {
00954     case OSL_PRECISION_SP: return lllog2(value.sp);
00955 
00956     case OSL_PRECISION_DP: return lllog2(value.dp);
00957 
00958 #ifdef OSL_GMP_IS_HERE
00959     case OSL_PRECISION_MP: return mpz_sizeinbase(*value.mp, 2);
00960 #endif
00961 
00962     default: OSL_error("unknown precision");
00963   }
00964 }
00965 
00966 
00967 // log10 function for long long int
00968 static size_t lllog10(long long int x) {
00969   size_t n = 0;
00970 
00971   x = llabs(x);
00972 
00973   while (x) { x /= 10; ++n; }
00974 
00975   return n;
00976 }
00977 
00983 size_t osl_int_size_in_base_10(int const precision,
00984                                osl_const_int_t const value) {
00985   switch (precision) {
00986     case OSL_PRECISION_SP: return lllog10(value.sp);
00987 
00988     case OSL_PRECISION_DP: return lllog10(value.dp);
00989 
00990 #ifdef OSL_GMP_IS_HERE
00991     case OSL_PRECISION_MP: return mpz_sizeinbase(*value.mp, 10);
00992 #endif
00993 
00994     default: OSL_error("unknown precision");
00995   }
00996 }
00997 
00998 
00999 /*+***************************************************************************
01000  *                            Conditional Operations                         *
01001  *****************************************************************************/
01002 
01003 
01007 int osl_int_eq(int precision, osl_const_int_t val1, osl_const_int_t val2) {
01008   switch (precision) {
01009     case OSL_PRECISION_SP:
01010       return (val1.sp == val2.sp);
01011 
01012     case OSL_PRECISION_DP:
01013       return (val1.dp == val2.dp);
01014 
01015 #ifdef OSL_GMP_IS_HERE
01016     case OSL_PRECISION_MP:
01017       return (mpz_cmp(*val1.mp, *val2.mp) == 0);
01018 #endif
01019 
01020     default:
01021       OSL_error("unknown precision");
01022   }
01023 }
01024 
01025 
01029 int osl_int_ne(int precision, osl_const_int_t val1, osl_const_int_t val2) {
01030   return !osl_int_eq(precision, val1, val2);
01031 }
01032 
01033 
01037 int osl_int_pos(int precision, osl_const_int_t value) {
01038   switch (precision) {
01039     case OSL_PRECISION_SP:
01040       return (value.sp > 0);
01041 
01042     case OSL_PRECISION_DP:
01043       return (value.dp > 0);
01044 
01045 #ifdef OSL_GMP_IS_HERE
01046     case OSL_PRECISION_MP:
01047       return (mpz_sgn(*value.mp) > 0);
01048 #endif
01049 
01050     default:
01051       OSL_error("unknown precision");
01052   }
01053 }
01054 
01055 
01059 int osl_int_neg(int precision, osl_const_int_t value) {
01060   switch (precision) {
01061     case OSL_PRECISION_SP:
01062       return (value.sp < 0);
01063 
01064     case OSL_PRECISION_DP:
01065       return (value.dp < 0);
01066 
01067 #ifdef OSL_GMP_IS_HERE
01068     case OSL_PRECISION_MP:
01069       return (mpz_sgn(*value.mp) < 0);
01070 #endif
01071 
01072     default:
01073       OSL_error("unknown precision");
01074   }
01075 }
01076 
01077 
01081 int osl_int_zero(int precision, osl_const_int_t value) {
01082   switch (precision) {
01083     case OSL_PRECISION_SP:
01084       return (value.sp == 0);
01085 
01086     case OSL_PRECISION_DP:
01087       return (value.dp == 0);
01088 
01089 #ifdef OSL_GMP_IS_HERE
01090     case OSL_PRECISION_MP:
01091       return (mpz_sgn(*value.mp) == 0);
01092 #endif
01093 
01094     default:
01095       OSL_error("unknown precision");
01096   }
01097 }
01098 
01099 
01103 int osl_int_one(int precision, osl_const_int_t value) {
01104   switch (precision) {
01105     case OSL_PRECISION_SP:
01106       return (value.sp == (long int)1);
01107 
01108     case OSL_PRECISION_DP:
01109       return (value.dp == (long long int)1);
01110 
01111 #ifdef OSL_GMP_IS_HERE
01112     case OSL_PRECISION_MP:
01113       return (mpz_cmp_si(*value.mp, 1) == 0);
01114 #endif
01115 
01116     default:
01117       OSL_error("unknown precision");
01118   }
01119 }
01120 
01121 
01125 int osl_int_mone(int precision, osl_const_int_t value) {
01126   switch (precision) {
01127     case OSL_PRECISION_SP:
01128       return (value.sp == (long int)-1);
01129 
01130     case OSL_PRECISION_DP:
01131       return (value.dp == (long long int)-1);
01132 
01133 #ifdef OSL_GMP_IS_HERE
01134     case OSL_PRECISION_MP:
01135       return (mpz_cmp_si(*value.mp, -1) == 0);
01136 #endif
01137 
01138     default:
01139       OSL_error("unknown precision");
01140   }
01141 }
01142 
01143 
01147 int osl_int_divisible(int precision,
01148                       osl_const_int_t val1, osl_const_int_t val2) {
01149   switch (precision) {
01150     case OSL_PRECISION_SP:
01151       return ((val1.sp % val2.sp) == 0);
01152 
01153     case OSL_PRECISION_DP:
01154       return ((val1.dp % val2.dp) == 0);
01155 
01156 #ifdef OSL_GMP_IS_HERE
01157     case OSL_PRECISION_MP:
01158       return mpz_divisible_p(*val1.mp, *val2.mp);
01159 #endif
01160 
01161     default:
01162       OSL_error("unknown precision");
01163   }
01164 }