OpenScop
0.9.0
|
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 }