00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include <stdlib.h>
00064 #include <stdio.h>
00065 #ifdef OSL_GMP_IS_HERE
00066 # include <gmp.h>
00067 #endif
00068
00069 #include <osl/macros.h>
00070 #include <osl/int.h>
00071
00072
00073
00074
00075
00076
00077
00078
00086 void osl_int_dump_precision(FILE * file, int precision) {
00087
00088 switch (precision) {
00089 case OSL_PRECISION_SP:
00090 fprintf(file, "32 bits");
00091 break;
00092 case OSL_PRECISION_DP:
00093 fprintf(file, "64 bits");
00094 break;
00095 #ifdef OSL_GMP_IS_HERE
00096 case OSL_PRECISION_MP:
00097 fprintf(file, "GMP");
00098 break;
00099 #endif
00100 default:
00101 fprintf(file, "unknown precision %d", precision);
00102 }
00103 }
00104
00105
00106 int osl_int_sizeof(int precision) {
00107 switch (precision) {
00108 case OSL_PRECISION_SP:
00109 return sizeof(long int);
00110
00111 case OSL_PRECISION_DP:
00112 return sizeof(long long int);
00113
00114 #ifdef OSL_GMP_IS_HERE
00115 case OSL_PRECISION_MP:
00116 return sizeof(mpz_t);
00117 #endif
00118
00119 default:
00120 OSL_error("unknown precision");
00121 }
00122 }
00123
00124
00125 void * osl_int_address(int precision, void * base, int offset) {
00126 switch (precision) {
00127 case OSL_PRECISION_SP:
00128 return (long int *)base + offset;
00129
00130 case OSL_PRECISION_DP:
00131 return (long long int *)base + offset;
00132
00133 #ifdef OSL_GMP_IS_HERE
00134 case OSL_PRECISION_MP:
00135 return (mpz_t *)base + offset;
00136 #endif
00137
00138 default:
00139 OSL_error("unknown precision");
00140 }
00141 }
00142
00143
00144 void osl_int_init(int precision, void * value_base, int value_offset) {
00145 void * value = osl_int_address(precision, value_base, value_offset);
00146
00147 switch (precision) {
00148 case OSL_PRECISION_SP:
00149 *(long int *)value = 0;
00150 break;
00151
00152 case OSL_PRECISION_DP:
00153 *(long long int *)value = 0;
00154 break;
00155
00156 #ifdef OSL_GMP_IS_HERE
00157 case OSL_PRECISION_MP:
00158 mpz_init(*(mpz_t *)value);
00159 break;
00160 #endif
00161
00162 default:
00163 OSL_error("unknown precision");
00164 }
00165 }
00166
00167
00168 void * osl_int_malloc(int precision) {
00169 void * value;
00170
00171 switch (precision) {
00172 case OSL_PRECISION_SP:
00173 value = malloc(sizeof(long int));
00174 break;
00175
00176 case OSL_PRECISION_DP:
00177 value = malloc(sizeof(long long int));
00178 *(long long int *)value = 0;
00179 break;
00180
00181 #ifdef OSL_GMP_IS_HERE
00182 case OSL_PRECISION_MP:
00183 value = malloc(sizeof(mpz_t));
00184 break;
00185 #endif
00186
00187 default:
00188 OSL_error("unknown precision");
00189 }
00190
00191 osl_int_init(precision, value, 0);
00192 return value;
00193 }
00194
00195
00199 void osl_int_assign(int precision,
00200 void * val1_base, int val1_offset,
00201 void * val2_base, int val2_offset) {
00202 void * val1 = osl_int_address(precision, val1_base, val1_offset);
00203 void * val2 = osl_int_address(precision, val2_base, val2_offset);
00204
00205 switch (precision) {
00206 case OSL_PRECISION_SP:
00207 *(long int *)val1 = *(long int *)val2;
00208 break;
00209
00210 case OSL_PRECISION_DP:
00211 *(long long int *)val1 = *(long long int *)val2;
00212 break;
00213
00214 #ifdef OSL_GMP_IS_HERE
00215 case OSL_PRECISION_MP:
00216 mpz_set(*(mpz_t *)val1, *(mpz_t *)val2);
00217 break;
00218 #endif
00219
00220 default:
00221 OSL_error("unknown precision");
00222 }
00223 }
00224
00225
00229 void osl_int_set_si(int precision, void * value_base, int value_offset,
00230 int i) {
00231 void * value = osl_int_address(precision, value_base, value_offset);
00232
00233 switch (precision) {
00234 case OSL_PRECISION_SP:
00235 *(long int *)value = (long int)i;
00236 break;
00237
00238 case OSL_PRECISION_DP:
00239 *(long long int *)value = (long long int)i;
00240 break;
00241
00242 #ifdef OSL_GMP_IS_HERE
00243 case OSL_PRECISION_MP:
00244 mpz_set_si(*(mpz_t *)value, i);
00245 break;
00246 #endif
00247
00248 default:
00249 OSL_error("unknown precision");
00250 }
00251 }
00252
00253
00257 int osl_int_get_si(int precision, void * value_base, int value_offset) {
00258 void * value = osl_int_address(precision, value_base, value_offset);
00259
00260 switch (precision) {
00261 case OSL_PRECISION_SP:
00262 return *(int *)value;
00263
00264 case OSL_PRECISION_DP:
00265 return *(int *)value;
00266
00267 #ifdef OSL_GMP_IS_HERE
00268 case OSL_PRECISION_MP:
00269 return mpz_get_si(*(mpz_t *)value);
00270 #endif
00271
00272 default:
00273 OSL_error("unknown precision");
00274 }
00275 }
00276
00277
00281 void osl_int_init_set_si(int precision,
00282 void * value_base, int value_offset, int i) {
00283 void * value = osl_int_address(precision, value_base, value_offset);
00284
00285 switch (precision) {
00286 case OSL_PRECISION_SP:
00287 *(long int *)value = (long int)i;
00288 break;
00289
00290 case OSL_PRECISION_DP:
00291 *(long long int *)value = (long long int)i;
00292 break;
00293
00294 #ifdef OSL_GMP_IS_HERE
00295 case OSL_PRECISION_MP:
00296 mpz_init_set_si(*(mpz_t *)value, i);
00297 break;
00298 #endif
00299
00300 default:
00301 OSL_error("unknown precision");
00302 }
00303 }
00304
00305
00309 void osl_int_clear(int precision, void * value_base, int value_offset) {
00310 void * value = osl_int_address(precision, value_base, value_offset);
00311
00312 switch (precision) {
00313 case OSL_PRECISION_SP:
00314 *(long int *)value = 0;
00315 break;
00316
00317 case OSL_PRECISION_DP:
00318 *(long long int *)value = 0;
00319 break;
00320
00321 #ifdef OSL_GMP_IS_HERE
00322 case OSL_PRECISION_MP:
00323 mpz_clear(*(mpz_t *)value);
00324 break;
00325 #endif
00326
00327 default:
00328 OSL_error("unknown precision");
00329 }
00330 }
00331
00332
00333 void osl_int_free(int precision, void * value_base, int value_offset) {
00334 void * value = osl_int_address(precision, value_base, value_offset);
00335
00336 osl_int_clear(precision, value_base, value_offset);
00337 free(value);
00338 }
00339
00340
00349 void osl_int_print(FILE * file, int precision,
00350 void * value_base, int value_offset) {
00351 char string[OSL_MAX_STRING];
00352
00353 osl_int_sprint(string, precision, value_base, value_offset);
00354 fprintf(file, "%s", string);
00355 }
00356
00357
00367 void osl_int_sprint(char * string, int precision,
00368 void * value_base, int value_offset) {
00369 void * value = osl_int_address(precision, value_base, value_offset);
00370
00371 switch (precision) {
00372 case OSL_PRECISION_SP:
00373 sprintf(string, OSL_FMT_SP, *(long int *)value);
00374 break;
00375
00376 case OSL_PRECISION_DP:
00377 sprintf(string, OSL_FMT_DP, *(long long int *)value);
00378 break;
00379
00380 #ifdef OSL_GMP_IS_HERE
00381 case OSL_PRECISION_MP: {
00382 char * str;
00383 str = mpz_get_str(0, 10, *(mpz_t *)value);
00384 sprintf(string, OSL_FMT_MP, str);
00385 free(str);
00386 break;
00387 }
00388 #endif
00389
00390 default:
00391 OSL_error("unknown precision");
00392 }
00393 }
00394
00395
00402 void osl_int_sprint_txt(char * string, int precision,
00403 void * value_base, int value_offset) {
00404 void * value = osl_int_address(precision, value_base, value_offset);
00405
00406 switch (precision) {
00407 case OSL_PRECISION_SP:
00408 sprintf(string, OSL_FMT_TXT_SP, *(long int *)value);
00409 break;
00410
00411 case OSL_PRECISION_DP:
00412 sprintf(string, OSL_FMT_TXT_DP, *(long long int *)value);
00413 break;
00414
00415 #ifdef OSL_GMP_IS_HERE
00416 case OSL_PRECISION_MP: {
00417 char * str;
00418 str = mpz_get_str(0, 10, *(mpz_t *)value);
00419 sprintf(string, OSL_FMT_TXT_MP, str);
00420 free(str);
00421 break;
00422 }
00423 #endif
00424
00425 default:
00426 OSL_error("unknown precision");
00427 }
00428 }
00429
00430
00431 void osl_int_sread(char ** string, int precision,
00432 void * value_base, int value_offset) {
00433 void * value = osl_int_address(precision, value_base, value_offset);
00434 int nb_read = 0;
00435
00436 switch (precision) {
00437 case OSL_PRECISION_SP:
00438 nb_read = sscanf(*string, OSL_FMT_TXT_SP, (long int *)value);
00439 if (nb_read == 0)
00440 OSL_error("failed to read an integer");
00441 break;
00442
00443 case OSL_PRECISION_DP:
00444 nb_read = sscanf(*string, OSL_FMT_TXT_DP, (long long int *)value);
00445 if (nb_read == 0)
00446 OSL_error("failed to read an integer");
00447 break;
00448
00449 #ifdef OSL_GMP_IS_HERE
00450 case OSL_PRECISION_MP: {
00451 long long int tmp;
00452 nb_read = sscanf(*string, OSL_FMT_TXT_DP, &tmp);
00453 if (nb_read == 0)
00454 OSL_error("failed to read an integer");
00455 mpz_set_si(*(mpz_t *)value, tmp);
00456 break;
00457 }
00458 #endif
00459
00460 default:
00461 OSL_error("unknown precision");
00462 }
00463
00464
00465 *string = *string + nb_read;
00466 }
00467
00468
00469
00470
00471
00472
00473
00477 void osl_int_increment(int precision,
00478 void * result_base, int result_offset,
00479 void * value_base, int value_offset) {
00480 void * result = osl_int_address(precision, result_base, result_offset);
00481 void * value = osl_int_address(precision, value_base, value_offset);
00482
00483 switch (precision) {
00484 case OSL_PRECISION_SP:
00485 *(long int *)result = *(long int *)value + (long int)1;
00486 break;
00487
00488 case OSL_PRECISION_DP:
00489 *(long long int *)result = *(long long int *)value + (long long int)1;
00490 break;
00491
00492 #ifdef OSL_GMP_IS_HERE
00493 case OSL_PRECISION_MP:
00494 mpz_add_ui(*(mpz_t *)result, *(mpz_t *)value, 1);
00495 break;
00496 #endif
00497
00498 default:
00499 OSL_error("unknown precision");
00500 }
00501 }
00502
00503
00507 void osl_int_decrement(int precision,
00508 void * result_base, int result_offset,
00509 void * value_base, int value_offset) {
00510 void * result = osl_int_address(precision, result_base, result_offset);
00511 void * value = osl_int_address(precision, value_base, value_offset);
00512
00513 switch (precision) {
00514 case OSL_PRECISION_SP:
00515 *(long int *)result = *(long int *)value - (long int)1;
00516 break;
00517
00518 case OSL_PRECISION_DP:
00519 *(long long int *)result = *(long long int *)value - (long long int)1;
00520 break;
00521
00522 #ifdef OSL_GMP_IS_HERE
00523 case OSL_PRECISION_MP: {
00524 mpz_t one;
00525 mpz_init_set_si(one, 1);
00526 mpz_sub(*(mpz_t *)result, *(mpz_t *)value, one);
00527 mpz_clear(one);
00528 break;
00529 }
00530 #endif
00531
00532 default:
00533 OSL_error("unknown precision");
00534 }
00535 }
00536
00537
00541 void osl_int_add(int precision,
00542 void * result_base, int result_offset,
00543 void * val1_base, int val1_offset,
00544 void * val2_base, int val2_offset) {
00545 void * result = osl_int_address(precision, result_base, result_offset);
00546 void * val1 = osl_int_address(precision, val1_base, val1_offset);
00547 void * val2 = osl_int_address(precision, val2_base, val2_offset);
00548
00549 switch (precision) {
00550 case OSL_PRECISION_SP:
00551 *(long int *)result = *(long int *)val1 + *(long int *)val2;
00552 break;
00553
00554 case OSL_PRECISION_DP:
00555 *(long long int *)result = *(long long int *)val1 +
00556 *(long long int *)val2;
00557 break;
00558
00559 #ifdef OSL_GMP_IS_HERE
00560 case OSL_PRECISION_MP:
00561 mpz_add(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
00562 break;
00563 #endif
00564
00565 default:
00566 OSL_error("unknown precision");
00567 }
00568 }
00569
00570
00574 void osl_int_add_si(int precision,
00575 void * result_base, int result_offset,
00576 void * value_base, int value_offset, int i) {
00577 void * result = osl_int_address(precision, result_base, result_offset);
00578 void * value = osl_int_address(precision, value_base, value_offset);
00579
00580 switch (precision) {
00581 case OSL_PRECISION_SP:
00582 *(long int *)result = *(long int *)value + (long int)i;
00583 break;
00584
00585 case OSL_PRECISION_DP:
00586 *(long long int *)result = *(long long int *)value + (long long int)i;
00587 break;
00588
00589 #ifdef OSL_GMP_IS_HERE
00590 case OSL_PRECISION_MP: {
00591 mpz_t si;
00592 mpz_init_set_si(si, i);
00593 mpz_add(*(mpz_t *)result, *(mpz_t *)value, si);
00594 mpz_clear(si);
00595 break;
00596 }
00597 #endif
00598
00599 default:
00600 OSL_error("unknown precision");
00601 }
00602 }
00603
00604
00608 void osl_int_mul(int precision,
00609 void * result_base, int result_offset,
00610 void * val1_base, int val1_offset,
00611 void * val2_base, int val2_offset) {
00612 void * result = osl_int_address(precision, result_base, result_offset);
00613 void * val1 = osl_int_address(precision, val1_base, val1_offset);
00614 void * val2 = osl_int_address(precision, val2_base, val2_offset);
00615
00616 switch (precision) {
00617 case OSL_PRECISION_SP:
00618 *(long int *)result = *(long int *)val1 * *(long int *)val2;
00619 break;
00620
00621 case OSL_PRECISION_DP:
00622 *(long long int *)result = *(long long int *)val1 *
00623 *(long long int *)val2;
00624 break;
00625
00626 #ifdef OSL_GMP_IS_HERE
00627 case OSL_PRECISION_MP:
00628 mpz_mul(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
00629 break;
00630 #endif
00631
00632 default:
00633 OSL_error("unknown precision");
00634 }
00635 }
00636
00637
00641 void osl_int_mul_si(int precision,
00642 void * result_base, int result_offset,
00643 void * value_base, int value_offset, int i) {
00644 void * result = osl_int_address(precision, result_base, result_offset);
00645 void * value = osl_int_address(precision, value_base, value_offset);
00646
00647 switch (precision) {
00648 case OSL_PRECISION_SP:
00649 *(long int *)result = *(long int *)value * (long int)i;
00650 break;
00651
00652 case OSL_PRECISION_DP:
00653 *(long long int *)result = *(long long int *)value * (long long int)i;
00654 break;
00655
00656 #ifdef OSL_GMP_IS_HERE
00657 case OSL_PRECISION_MP:
00658 mpz_mul_si(*(mpz_t *)result, *(mpz_t *)value, i);
00659 break;
00660 #endif
00661
00662 default:
00663 OSL_error("unknown precision");
00664 }
00665 }
00666
00667
00671 void osl_int_sub(int precision,
00672 void * result_base, int result_offset,
00673 void * val1_base, int val1_offset,
00674 void * val2_base, int val2_offset) {
00675 void * result = osl_int_address(precision, result_base, result_offset);
00676 void * val1 = osl_int_address(precision, val1_base, val1_offset);
00677 void * val2 = osl_int_address(precision, val2_base, val2_offset);
00678
00679 switch (precision) {
00680 case OSL_PRECISION_SP:
00681 *(long int *)result = *(long int *)val1 - *(long int *)val2;
00682 break;
00683
00684 case OSL_PRECISION_DP:
00685 *(long long int *)result = *(long long int *)val1 -
00686 *(long long int *)val2;
00687 break;
00688
00689 #ifdef OSL_GMP_IS_HERE
00690 case OSL_PRECISION_MP:
00691 mpz_sub(*(mpz_t *)result, *(mpz_t *)val1, *(mpz_t *)val2);
00692 break;
00693 #endif
00694
00695 default:
00696 OSL_error("unknown precision");
00697 }
00698 }
00699
00700
00704 void osl_int_oppose(int precision,
00705 void * result_base, int result_offset,
00706 void * value_base, int value_offset) {
00707 void * result = osl_int_address(precision, result_base, result_offset);
00708 void * value = osl_int_address(precision, value_base, value_offset);
00709
00710 switch (precision) {
00711 case OSL_PRECISION_SP:
00712 *(long int *)result = -*(long int *)value;
00713 break;
00714
00715 case OSL_PRECISION_DP:
00716 *(long long int *)result = -*(long long int *)value;
00717 break;
00718
00719 #ifdef OSL_GMP_IS_HERE
00720 case OSL_PRECISION_MP:
00721 mpz_neg(*(mpz_t *)result, *(mpz_t *)value);
00722 break;
00723 #endif
00724
00725 default:
00726 OSL_error("unknown precision");
00727 }
00728 }
00729
00730
00731
00732
00733
00734
00735
00739 int osl_int_eq(int precision,
00740 void * val1_base, int val1_offset,
00741 void * val2_base, int val2_offset) {
00742 void * val1 = osl_int_address(precision, val1_base, val1_offset);
00743 void * val2 = osl_int_address(precision, val2_base, val2_offset);
00744
00745 switch (precision) {
00746 case OSL_PRECISION_SP:
00747 return (*(long int *)val1 == *(long int *)val2);
00748
00749 case OSL_PRECISION_DP:
00750 return (*(long long int *)val1 == *(long long int *)val2);
00751
00752 #ifdef OSL_GMP_IS_HERE
00753 case OSL_PRECISION_MP:
00754 return (mpz_cmp(*(mpz_t *)val1, *(mpz_t *)val2) == 0);
00755 #endif
00756
00757 default:
00758 OSL_error("unknown precision");
00759 }
00760 }
00761
00762
00766 int osl_int_ne(int precision,
00767 void * val1_base, int val1_offset,
00768 void * val2_base, int val2_offset) {
00769 return !osl_int_eq(precision,
00770 val1_base, val1_offset,
00771 val2_base, val2_offset);
00772 }
00773
00774
00778 int osl_int_pos(int precision, void * value_base, int value_offset) {
00779 void * value = osl_int_address(precision, value_base, value_offset);
00780
00781 switch (precision) {
00782 case OSL_PRECISION_SP:
00783 return (*(long int *)value > 0);
00784
00785 case OSL_PRECISION_DP:
00786 return (*(long long int *)value > 0);
00787
00788 #ifdef OSL_GMP_IS_HERE
00789 case OSL_PRECISION_MP:
00790 return (mpz_sgn(*(mpz_t *)value) > 0);
00791 #endif
00792
00793 default:
00794 OSL_error("unknown precision");
00795 }
00796 }
00797
00798
00802 int osl_int_neg(int precision, void * value_base, int value_offset) {
00803 void * value = osl_int_address(precision, value_base, value_offset);
00804
00805 switch (precision) {
00806 case OSL_PRECISION_SP:
00807 return (*(long int *)value < 0);
00808
00809 case OSL_PRECISION_DP:
00810 return (*(long long int *)value < 0);
00811
00812 #ifdef OSL_GMP_IS_HERE
00813 case OSL_PRECISION_MP:
00814 return (mpz_sgn(*(mpz_t *)value) < 0);
00815 #endif
00816
00817 default:
00818 OSL_error("unknown precision");
00819 }
00820 }
00821
00822
00826 int osl_int_zero(int precision, void * value_base, int value_offset) {
00827 void * value = osl_int_address(precision, value_base, value_offset);
00828
00829 switch (precision) {
00830 case OSL_PRECISION_SP:
00831 return (*(long int *)value == 0);
00832
00833 case OSL_PRECISION_DP:
00834 return (*(long long int *)value == 0);
00835
00836 #ifdef OSL_GMP_IS_HERE
00837 case OSL_PRECISION_MP:
00838 return (mpz_sgn(*(mpz_t *)value) == 0);
00839 #endif
00840
00841 default:
00842 OSL_error("unknown precision");
00843 }
00844 }
00845
00846
00850 int osl_int_one(int precision, void * value_base, int value_offset) {
00851 void * value = osl_int_address(precision, value_base, value_offset);
00852
00853 switch (precision) {
00854 case OSL_PRECISION_SP:
00855 return (*(long int *)value == (long int)1);
00856
00857 case OSL_PRECISION_DP:
00858 return (*(long long int *)value == (long long int)1);
00859
00860 #ifdef OSL_GMP_IS_HERE
00861 case OSL_PRECISION_MP:
00862 return (mpz_cmp_si(*(mpz_t *)value, 1) == 0);
00863 #endif
00864
00865 default:
00866 OSL_error("unknown precision");
00867 }
00868 }
00869
00870
00874 int osl_int_mone(int precision, void * value_base, int value_offset) {
00875 void * value = osl_int_address(precision, value_base, value_offset);
00876
00877 switch (precision) {
00878 case OSL_PRECISION_SP:
00879 return (*(long int *)value == (long int)-1);
00880
00881 case OSL_PRECISION_DP:
00882 return (*(long long int *)value == (long long int)-1);
00883
00884 #ifdef OSL_GMP_IS_HERE
00885 case OSL_PRECISION_MP:
00886 return (mpz_cmp_si(*(mpz_t *)value, -1) == 0);
00887 #endif
00888
00889 default:
00890 OSL_error("unknown precision");
00891 }
00892 }
00893
00894
00898 int osl_int_divisible(int precision,
00899 void * val1_base, int val1_offset,
00900 void * val2_base, int val2_offset) {
00901 void * val1 = osl_int_address(precision, val1_base, val1_offset);
00902 void * val2 = osl_int_address(precision, val2_base, val2_offset);
00903
00904 switch (precision) {
00905 case OSL_PRECISION_SP:
00906 return ((*(long int *)val1 % *(long int *)val2) == 0);
00907
00908 case OSL_PRECISION_DP:
00909 return ((*(long long int *)val1 % *(long long int *)val2) == 0);
00910
00911 #ifdef OSL_GMP_IS_HERE
00912 case OSL_PRECISION_MP:
00913 return mpz_divisible_p(*(mpz_t *)val1, *(mpz_t *)val2);
00914 #endif
00915
00916 default:
00917 OSL_error("unknown precision");
00918 }
00919 }