1 /* 2 * Copyright 2015 INRIA Paris-Rocquencourt 3 * 4 * Use of this software is governed by the MIT license 5 * 6 * Written by Michael Kruse, INRIA Paris-Rocquencourt, 7 * Domaine de Voluceau, Rocquenqourt, B.P. 105, 8 * 78153 Le Chesnay Cedex France 9 */ 10 #ifndef ISL_INT_SIOIMATH_H 11 #define ISL_INT_SIOIMATH_H 12 13 #include <inttypes.h> 14 #include <limits.h> 15 #include <stdint.h> 16 #include <stdlib.h> 17 18 #include <isl_imath.h> 19 #include <isl/hash.h> 20 21 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array)) 22 23 /* Visual Studio before VS2015 does not support the inline keyword when 24 * compiling in C mode because it was introduced in C99 which it does not 25 * officially support. Instead, it has a proprietary extension using __inline. 26 */ 27 #if defined(_MSC_VER) && (_MSC_VER < 1900) 28 #define inline __inline 29 #endif 30 31 /* The type to represent integers optimized for small values. It is either a 32 * pointer to an mp_int ( = mpz_t*; big representation) or an int32_t (small 33 * represenation) with a discriminator at the least significant bit. In big 34 * representation it will be always zero because of heap alignment. It is set 35 * to 1 for small representation and use the 32 most significant bits for the 36 * int32_t. 37 * 38 * Structure on 64 bit machines, with 8-byte aligment (3 bits): 39 * 40 * Big representation: 41 * MSB LSB 42 * |------------------------------------------------------------000 43 * | mpz_t* | 44 * | != NULL | 45 * 46 * Small representation: 47 * MSB 32 LSB 48 * |------------------------------|00000000000000000000000000000001 49 * | int32_t | 50 * | 2147483647 ... -2147483647 | 51 * ^ 52 * | 53 * discriminator bit 54 * 55 * On 32 bit machines isl_sioimath type is blown up to 8 bytes, i.e. 56 * isl_sioimath is guaranteed to be at least 8 bytes. This is to ensure the 57 * int32_t can be hidden in that type without data loss. In the future we might 58 * optimize this to use 31 hidden bits in a 32 bit pointer. We may also use 63 59 * bits on 64 bit machines, but this comes with the cost of additional overflow 60 * checks because there is no standardized 128 bit integer we could expand to. 61 * 62 * We use native integer types and avoid union structures to avoid assumptions 63 * on the machine's endianness. 64 * 65 * This implementation makes the following assumptions: 66 * - long can represent any int32_t 67 * - mp_small is signed long 68 * - mp_usmall is unsigned long 69 * - adresses returned by malloc are aligned to 2-byte boundaries (leastmost 70 * bit is zero) 71 */ 72 #if UINT64_MAX > UINTPTR_MAX 73 typedef uint64_t isl_sioimath; 74 #else 75 typedef uintptr_t isl_sioimath; 76 #endif 77 78 /* The negation of the smallest possible number in int32_t, INT32_MIN 79 * (0x80000000u, -2147483648), cannot be represented in an int32_t, therefore 80 * every operation that may produce this value needs to special-case it. 81 * The operations are: 82 * abs(INT32_MIN) 83 * -INT32_MIN (negation) 84 * -1 * INT32_MIN (multiplication) 85 * INT32_MIN/-1 (any division: divexact, fdiv, cdiv, tdiv) 86 * To avoid checking these cases, we exclude INT32_MIN from small 87 * representation. 88 */ 89 #define ISL_SIOIMATH_SMALL_MIN (-INT32_MAX) 90 91 /* Largest possible number in small representation */ 92 #define ISL_SIOIMATH_SMALL_MAX INT32_MAX 93 94 /* Used for function parameters the function modifies. */ 95 typedef isl_sioimath *isl_sioimath_ptr; 96 97 /* Used for function parameters that are read-only. */ 98 typedef isl_sioimath isl_sioimath_src; 99 100 /* Return whether the argument is stored in small representation. 101 */ 102 inline int isl_sioimath_is_small(isl_sioimath val) 103 { 104 return val & 0x00000001; 105 } 106 107 /* Return whether the argument is stored in big representation. 108 */ 109 inline int isl_sioimath_is_big(isl_sioimath val) 110 { 111 return !isl_sioimath_is_small(val); 112 } 113 114 /* Get the number of an isl_int in small representation. Result is undefined if 115 * val is not stored in that format. 116 */ 117 inline int32_t isl_sioimath_get_small(isl_sioimath val) 118 { 119 return val >> 32; 120 } 121 122 /* Get the number of an in isl_int in big representation. Result is undefined if 123 * val is not stored in that format. 124 */ 125 inline mp_int isl_sioimath_get_big(isl_sioimath val) 126 { 127 return (mp_int)(uintptr_t) val; 128 } 129 130 /* Return 1 if val is stored in small representation and store its value to 131 * small. We rely on the compiler to optimize the isl_sioimath_get_small such 132 * that the shift is moved into the branch that executes in case of small 133 * representation. If there is no such branch, then a single shift is still 134 * cheaper than introducing branching code. 135 */ 136 inline int isl_sioimath_decode_small(isl_sioimath val, int32_t *small) 137 { 138 *small = isl_sioimath_get_small(val); 139 return isl_sioimath_is_small(val); 140 } 141 142 /* Return 1 if val is stored in big representation and store its value to big. 143 */ 144 inline int isl_sioimath_decode_big(isl_sioimath val, mp_int *big) 145 { 146 *big = isl_sioimath_get_big(val); 147 return isl_sioimath_is_big(val); 148 } 149 150 /* Encode a small representation into an isl_int. 151 */ 152 inline isl_sioimath isl_sioimath_encode_small(int32_t val) 153 { 154 return ((isl_sioimath) val) << 32 | 0x00000001; 155 } 156 157 /* Encode a big representation. 158 */ 159 inline isl_sioimath isl_sioimath_encode_big(mp_int val) 160 { 161 return (isl_sioimath)(uintptr_t) val; 162 } 163 164 /* A common situation is to call an IMath function with at least one argument 165 * that is currently in small representation or an integer parameter, i.e. a big 166 * representation of the same number is required. Promoting the original 167 * argument comes with multiple problems, such as modifying a read-only 168 * argument, the responsibility of deallocation and the execution cost. Instead, 169 * we make a copy by 'faking' the IMath internal structure. 170 * 171 * We reserve the maximum number of required digits on the stack to avoid heap 172 * allocations. 173 * 174 * mp_digit can be uint32_t or uint16_t. This code must work for little and big 175 * endian digits. The structure for an uint64_t argument and 32-bit mp_digits is 176 * sketched below. 177 * 178 * |----------------------------| 179 * uint64_t 180 * 181 * |-------------||-------------| 182 * mp_digit mp_digit 183 * digits[1] digits[0] 184 * Most sig digit Least sig digit 185 */ 186 typedef struct { 187 mpz_t big; 188 mp_digit digits[(sizeof(uintmax_t) + sizeof(mp_digit) - 1) / 189 sizeof(mp_digit)]; 190 } isl_sioimath_scratchspace_t; 191 192 /* Convert a native integer to IMath's digit representation. A native integer 193 * might be big- or little endian, but IMath always stores the least significant 194 * digit in the lowest array indices. memcpy therefore is not possible. 195 * 196 * We also have to consider that long and mp_digit can be of different sizes, 197 * depending on the compiler (LP64, LLP64) and IMath's USE_64BIT_WORDS. This 198 * macro should work for all of them. 199 * 200 * "used" is set to the number of written digits. It must be minimal (IMath 201 * checks zeroness using the used field), but always at least one. Also note 202 * that the result of num>>(sizeof(num)*CHAR_BIT) is undefined. 203 */ 204 #define ISL_SIOIMATH_TO_DIGITS(num, digits, used) \ 205 do { \ 206 int i = 0; \ 207 do { \ 208 (digits)[i] = \ 209 ((num) >> (sizeof(mp_digit) * CHAR_BIT * i)); \ 210 i += 1; \ 211 if (i >= (sizeof(num) + sizeof(mp_digit) - 1) / \ 212 sizeof(mp_digit)) \ 213 break; \ 214 if (((num) >> (sizeof(mp_digit) * CHAR_BIT * i)) == 0) \ 215 break; \ 216 } while (1); \ 217 (used) = i; \ 218 } while (0) 219 220 inline void isl_siomath_uint32_to_digits(uint32_t num, mp_digit *digits, 221 mp_size *used) 222 { 223 ISL_SIOIMATH_TO_DIGITS(num, digits, *used); 224 } 225 226 inline void isl_siomath_ulong_to_digits(unsigned long num, mp_digit *digits, 227 mp_size *used) 228 { 229 ISL_SIOIMATH_TO_DIGITS(num, digits, *used); 230 } 231 232 inline void isl_siomath_uint64_to_digits(uint64_t num, mp_digit *digits, 233 mp_size *used) 234 { 235 ISL_SIOIMATH_TO_DIGITS(num, digits, *used); 236 } 237 238 /* Get the IMath representation of an isl_int without modifying it. 239 * For the case it is not in big representation yet, pass some scratch space we 240 * can use to store the big representation in. 241 * In order to avoid requiring init and free on the scratch space, we directly 242 * modify the internal representation. 243 * 244 * The name derives from its indented use: getting the big representation of an 245 * input (src) argument. 246 */ 247 inline mp_int isl_sioimath_bigarg_src(isl_sioimath arg, 248 isl_sioimath_scratchspace_t *scratch) 249 { 250 mp_int big; 251 int32_t small; 252 uint32_t num; 253 254 if (isl_sioimath_decode_big(arg, &big)) 255 return big; 256 257 small = isl_sioimath_get_small(arg); 258 scratch->big.digits = scratch->digits; 259 scratch->big.alloc = ARRAY_SIZE(scratch->digits); 260 if (small >= 0) { 261 scratch->big.sign = MP_ZPOS; 262 num = small; 263 } else { 264 scratch->big.sign = MP_NEG; 265 num = -small; 266 } 267 268 isl_siomath_uint32_to_digits(num, scratch->digits, &scratch->big.used); 269 return &scratch->big; 270 } 271 272 /* Create a temporary IMath mp_int for a signed long. 273 */ 274 inline mp_int isl_sioimath_siarg_src(signed long arg, 275 isl_sioimath_scratchspace_t *scratch) 276 { 277 unsigned long num; 278 279 scratch->big.digits = scratch->digits; 280 scratch->big.alloc = ARRAY_SIZE(scratch->digits); 281 if (arg >= 0) { 282 scratch->big.sign = MP_ZPOS; 283 num = arg; 284 } else { 285 scratch->big.sign = MP_NEG; 286 num = (arg == LONG_MIN) ? ((unsigned long) LONG_MAX) + 1 : -arg; 287 } 288 289 isl_siomath_ulong_to_digits(num, scratch->digits, &scratch->big.used); 290 return &scratch->big; 291 } 292 293 /* Create a temporary IMath mp_int for an int64_t. 294 */ 295 inline mp_int isl_sioimath_si64arg_src(int64_t arg, 296 isl_sioimath_scratchspace_t *scratch) 297 { 298 uint64_t num; 299 300 scratch->big.digits = scratch->digits; 301 scratch->big.alloc = ARRAY_SIZE(scratch->digits); 302 if (arg >= 0) { 303 scratch->big.sign = MP_ZPOS; 304 num = arg; 305 } else { 306 scratch->big.sign = MP_NEG; 307 num = (arg == INT64_MIN) ? ((uint64_t) INT64_MAX) + 1 : -arg; 308 } 309 310 isl_siomath_uint64_to_digits(num, scratch->digits, &scratch->big.used); 311 return &scratch->big; 312 } 313 314 /* Create a temporary IMath mp_int for an unsigned long. 315 */ 316 inline mp_int isl_sioimath_uiarg_src(unsigned long arg, 317 isl_sioimath_scratchspace_t *scratch) 318 { 319 scratch->big.digits = scratch->digits; 320 scratch->big.alloc = ARRAY_SIZE(scratch->digits); 321 scratch->big.sign = MP_ZPOS; 322 323 isl_siomath_ulong_to_digits(arg, scratch->digits, &scratch->big.used); 324 return &scratch->big; 325 } 326 327 /* Ensure big representation. Does not preserve the current number. 328 * Callers may use the fact that the value _is_ preserved if the presentation 329 * was big before. 330 */ 331 inline mp_int isl_sioimath_reinit_big(isl_sioimath_ptr ptr) 332 { 333 if (isl_sioimath_is_small(*ptr)) 334 *ptr = isl_sioimath_encode_big(mp_int_alloc()); 335 return isl_sioimath_get_big(*ptr); 336 } 337 338 /* Set ptr to a number in small representation. 339 */ 340 inline void isl_sioimath_set_small(isl_sioimath_ptr ptr, int32_t val) 341 { 342 if (isl_sioimath_is_big(*ptr)) 343 mp_int_free(isl_sioimath_get_big(*ptr)); 344 *ptr = isl_sioimath_encode_small(val); 345 } 346 347 /* Set ptr to val, choosing small representation if possible. 348 */ 349 inline void isl_sioimath_set_int32(isl_sioimath_ptr ptr, int32_t val) 350 { 351 if (ISL_SIOIMATH_SMALL_MIN <= val && val <= ISL_SIOIMATH_SMALL_MAX) { 352 isl_sioimath_set_small(ptr, val); 353 return; 354 } 355 356 mp_int_init_value(isl_sioimath_reinit_big(ptr), val); 357 } 358 359 /* Assign an int64_t number using small representation if possible. 360 */ 361 inline void isl_sioimath_set_int64(isl_sioimath_ptr ptr, int64_t val) 362 { 363 if (ISL_SIOIMATH_SMALL_MIN <= val && val <= ISL_SIOIMATH_SMALL_MAX) { 364 isl_sioimath_set_small(ptr, val); 365 return; 366 } 367 368 isl_sioimath_scratchspace_t scratch; 369 mp_int_copy(isl_sioimath_si64arg_src(val, &scratch), 370 isl_sioimath_reinit_big(ptr)); 371 } 372 373 /* Convert to big representation while preserving the current number. 374 */ 375 inline void isl_sioimath_promote(isl_sioimath_ptr dst) 376 { 377 int32_t small; 378 379 if (isl_sioimath_is_big(*dst)) 380 return; 381 382 small = isl_sioimath_get_small(*dst); 383 mp_int_set_value(isl_sioimath_reinit_big(dst), small); 384 } 385 386 /* Convert to small representation while preserving the current number. Does 387 * nothing if dst doesn't fit small representation. 388 */ 389 inline void isl_sioimath_try_demote(isl_sioimath_ptr dst) 390 { 391 mp_small small; 392 393 if (isl_sioimath_is_small(*dst)) 394 return; 395 396 if (mp_int_to_int(isl_sioimath_get_big(*dst), &small) != MP_OK) 397 return; 398 399 if (ISL_SIOIMATH_SMALL_MIN <= small && small <= ISL_SIOIMATH_SMALL_MAX) 400 isl_sioimath_set_small(dst, small); 401 } 402 403 /* Initialize an isl_int. The implicit value is 0 in small representation. 404 */ 405 inline void isl_sioimath_init(isl_sioimath_ptr dst) 406 { 407 *dst = isl_sioimath_encode_small(0); 408 } 409 410 /* Free the resources taken by an isl_int. 411 */ 412 inline void isl_sioimath_clear(isl_sioimath_ptr dst) 413 { 414 if (isl_sioimath_is_small(*dst)) 415 return; 416 417 mp_int_free(isl_sioimath_get_big(*dst)); 418 } 419 420 /* Copy the value of one isl_int to another. 421 */ 422 inline void isl_sioimath_set(isl_sioimath_ptr dst, isl_sioimath_src val) 423 { 424 if (isl_sioimath_is_small(val)) { 425 isl_sioimath_set_small(dst, isl_sioimath_get_small(val)); 426 return; 427 } 428 429 mp_int_copy(isl_sioimath_get_big(val), isl_sioimath_reinit_big(dst)); 430 } 431 432 /* Store a signed long into an isl_int. 433 */ 434 inline void isl_sioimath_set_si(isl_sioimath_ptr dst, long val) 435 { 436 if (ISL_SIOIMATH_SMALL_MIN <= val && val <= ISL_SIOIMATH_SMALL_MAX) { 437 isl_sioimath_set_small(dst, val); 438 return; 439 } 440 441 mp_int_set_value(isl_sioimath_reinit_big(dst), val); 442 } 443 444 /* Store an unsigned long into an isl_int. 445 */ 446 inline void isl_sioimath_set_ui(isl_sioimath_ptr dst, unsigned long val) 447 { 448 if (val <= ISL_SIOIMATH_SMALL_MAX) { 449 isl_sioimath_set_small(dst, val); 450 return; 451 } 452 453 mp_int_set_uvalue(isl_sioimath_reinit_big(dst), val); 454 } 455 456 /* Return whether a number can be represented by a signed long. 457 */ 458 inline int isl_sioimath_fits_slong(isl_sioimath_src val) 459 { 460 mp_small dummy; 461 462 if (isl_sioimath_is_small(val)) 463 return 1; 464 465 return mp_int_to_int(isl_sioimath_get_big(val), &dummy) == MP_OK; 466 } 467 468 /* Return a number as signed long. Result is undefined if the number cannot be 469 * represented as long. 470 */ 471 inline long isl_sioimath_get_si(isl_sioimath_src val) 472 { 473 mp_small result; 474 475 if (isl_sioimath_is_small(val)) 476 return isl_sioimath_get_small(val); 477 478 mp_int_to_int(isl_sioimath_get_big(val), &result); 479 return result; 480 } 481 482 /* Return whether a number can be represented as unsigned long. 483 */ 484 inline int isl_sioimath_fits_ulong(isl_sioimath_src val) 485 { 486 mp_usmall dummy; 487 488 if (isl_sioimath_is_small(val)) 489 return isl_sioimath_get_small(val) >= 0; 490 491 return mp_int_to_uint(isl_sioimath_get_big(val), &dummy) == MP_OK; 492 } 493 494 /* Return a number as unsigned long. Result is undefined if the number cannot be 495 * represented as unsigned long. 496 */ 497 inline unsigned long isl_sioimath_get_ui(isl_sioimath_src val) 498 { 499 mp_usmall result; 500 501 if (isl_sioimath_is_small(val)) 502 return isl_sioimath_get_small(val); 503 504 mp_int_to_uint(isl_sioimath_get_big(val), &result); 505 return result; 506 } 507 508 /* Return a number as floating point value. 509 */ 510 inline double isl_sioimath_get_d(isl_sioimath_src val) 511 { 512 mp_int big; 513 double result = 0; 514 int i; 515 516 if (isl_sioimath_is_small(val)) 517 return isl_sioimath_get_small(val); 518 519 big = isl_sioimath_get_big(val); 520 for (i = 0; i < big->used; ++i) 521 result = result * (double) ((uintmax_t) MP_DIGIT_MAX + 1) + 522 (double) big->digits[i]; 523 524 if (big->sign == MP_NEG) 525 result = -result; 526 527 return result; 528 } 529 530 /* Format a number as decimal string. 531 * 532 * The largest possible string from small representation is 12 characters 533 * ("-2147483647"). 534 */ 535 inline char *isl_sioimath_get_str(isl_sioimath_src val) 536 { 537 char *result; 538 539 if (isl_sioimath_is_small(val)) { 540 result = malloc(12); 541 snprintf(result, 12, "%" PRIi32, isl_sioimath_get_small(val)); 542 return result; 543 } 544 545 return impz_get_str(NULL, 10, isl_sioimath_get_big(val)); 546 } 547 548 /* Return the absolute value. 549 */ 550 inline void isl_sioimath_abs(isl_sioimath_ptr dst, isl_sioimath_src arg) 551 { 552 if (isl_sioimath_is_small(arg)) { 553 isl_sioimath_set_small(dst, labs(isl_sioimath_get_small(arg))); 554 return; 555 } 556 557 mp_int_abs(isl_sioimath_get_big(arg), isl_sioimath_reinit_big(dst)); 558 } 559 560 /* Return the negation of a number. 561 */ 562 inline void isl_sioimath_neg(isl_sioimath_ptr dst, isl_sioimath_src arg) 563 { 564 if (isl_sioimath_is_small(arg)) { 565 isl_sioimath_set_small(dst, -isl_sioimath_get_small(arg)); 566 return; 567 } 568 569 mp_int_neg(isl_sioimath_get_big(arg), isl_sioimath_reinit_big(dst)); 570 } 571 572 /* Swap two isl_ints. 573 * 574 * isl_sioimath can be copied bytewise; nothing depends on its address. It can 575 * also be stored in a CPU register. 576 */ 577 inline void isl_sioimath_swap(isl_sioimath_ptr lhs, isl_sioimath_ptr rhs) 578 { 579 isl_sioimath tmp = *lhs; 580 *lhs = *rhs; 581 *rhs = tmp; 582 } 583 584 /* Add an unsigned long to the number. 585 * 586 * On LP64 unsigned long exceeds the range of an int64_t, therefore we check in 587 * advance whether small representation possibly overflows. 588 */ 589 inline void isl_sioimath_add_ui(isl_sioimath_ptr dst, isl_sioimath lhs, 590 unsigned long rhs) 591 { 592 int32_t smalllhs; 593 isl_sioimath_scratchspace_t lhsscratch; 594 595 if (isl_sioimath_decode_small(lhs, &smalllhs) && 596 (rhs <= (uint64_t) INT64_MAX - (uint64_t) ISL_SIOIMATH_SMALL_MAX)) { 597 isl_sioimath_set_int64(dst, (int64_t) smalllhs + rhs); 598 return; 599 } 600 601 impz_add_ui(isl_sioimath_reinit_big(dst), 602 isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs); 603 isl_sioimath_try_demote(dst); 604 } 605 606 /* Subtract an unsigned long. 607 * 608 * On LP64 unsigned long exceeds the range of an int64_t. If 609 * ISL_SIOIMATH_SMALL_MIN-rhs>=INT64_MIN we can do the calculation using int64_t 610 * without risking an overflow. 611 */ 612 inline void isl_sioimath_sub_ui(isl_sioimath_ptr dst, isl_sioimath lhs, 613 unsigned long rhs) 614 { 615 int32_t smalllhs; 616 isl_sioimath_scratchspace_t lhsscratch; 617 618 if (isl_sioimath_decode_small(lhs, &smalllhs) && 619 (rhs < (uint64_t) INT64_MIN - (uint64_t) ISL_SIOIMATH_SMALL_MIN)) { 620 isl_sioimath_set_int64(dst, (int64_t) smalllhs - rhs); 621 return; 622 } 623 624 impz_sub_ui(isl_sioimath_reinit_big(dst), 625 isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs); 626 isl_sioimath_try_demote(dst); 627 } 628 629 /* Sum of two isl_ints. 630 */ 631 inline void isl_sioimath_add(isl_sioimath_ptr dst, isl_sioimath_src lhs, 632 isl_sioimath_src rhs) 633 { 634 isl_sioimath_scratchspace_t scratchlhs, scratchrhs; 635 int32_t smalllhs, smallrhs; 636 637 if (isl_sioimath_decode_small(lhs, &smalllhs) && 638 isl_sioimath_decode_small(rhs, &smallrhs)) { 639 isl_sioimath_set_int64( 640 dst, (int64_t) smalllhs + (int64_t) smallrhs); 641 return; 642 } 643 644 mp_int_add(isl_sioimath_bigarg_src(lhs, &scratchlhs), 645 isl_sioimath_bigarg_src(rhs, &scratchrhs), 646 isl_sioimath_reinit_big(dst)); 647 isl_sioimath_try_demote(dst); 648 } 649 650 /* Subtract two isl_ints. 651 */ 652 inline void isl_sioimath_sub(isl_sioimath_ptr dst, isl_sioimath_src lhs, 653 isl_sioimath_src rhs) 654 { 655 isl_sioimath_scratchspace_t scratchlhs, scratchrhs; 656 int32_t smalllhs, smallrhs; 657 658 if (isl_sioimath_decode_small(lhs, &smalllhs) && 659 isl_sioimath_decode_small(rhs, &smallrhs)) { 660 isl_sioimath_set_int64( 661 dst, (int64_t) smalllhs - (int64_t) smallrhs); 662 return; 663 } 664 665 mp_int_sub(isl_sioimath_bigarg_src(lhs, &scratchlhs), 666 isl_sioimath_bigarg_src(rhs, &scratchrhs), 667 isl_sioimath_reinit_big(dst)); 668 isl_sioimath_try_demote(dst); 669 } 670 671 /* Multiply two isl_ints. 672 */ 673 inline void isl_sioimath_mul(isl_sioimath_ptr dst, isl_sioimath_src lhs, 674 isl_sioimath_src rhs) 675 { 676 isl_sioimath_scratchspace_t scratchlhs, scratchrhs; 677 int32_t smalllhs, smallrhs; 678 679 if (isl_sioimath_decode_small(lhs, &smalllhs) && 680 isl_sioimath_decode_small(rhs, &smallrhs)) { 681 isl_sioimath_set_int64( 682 dst, (int64_t) smalllhs * (int64_t) smallrhs); 683 return; 684 } 685 686 mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs), 687 isl_sioimath_bigarg_src(rhs, &scratchrhs), 688 isl_sioimath_reinit_big(dst)); 689 isl_sioimath_try_demote(dst); 690 } 691 692 /* Shift lhs by rhs bits to the left and store the result in dst. Effectively, 693 * this operation computes 'lhs * 2^rhs'. 694 */ 695 inline void isl_sioimath_mul_2exp(isl_sioimath_ptr dst, isl_sioimath lhs, 696 unsigned long rhs) 697 { 698 isl_sioimath_scratchspace_t scratchlhs; 699 int32_t smalllhs; 700 701 if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs <= 32ul)) { 702 isl_sioimath_set_int64(dst, ((int64_t) smalllhs) << rhs); 703 return; 704 } 705 706 mp_int_mul_pow2(isl_sioimath_bigarg_src(lhs, &scratchlhs), rhs, 707 isl_sioimath_reinit_big(dst)); 708 } 709 710 /* Multiply an isl_int and a signed long. 711 */ 712 inline void isl_sioimath_mul_si(isl_sioimath_ptr dst, isl_sioimath lhs, 713 signed long rhs) 714 { 715 isl_sioimath_scratchspace_t scratchlhs, scratchrhs; 716 int32_t smalllhs; 717 718 if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs > LONG_MIN) && 719 (labs(rhs) <= UINT32_MAX)) { 720 isl_sioimath_set_int64(dst, (int64_t) smalllhs * (int64_t) rhs); 721 return; 722 } 723 724 mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs), 725 isl_sioimath_siarg_src(rhs, &scratchrhs), 726 isl_sioimath_reinit_big(dst)); 727 isl_sioimath_try_demote(dst); 728 } 729 730 /* Multiply an isl_int and an unsigned long. 731 */ 732 inline void isl_sioimath_mul_ui(isl_sioimath_ptr dst, isl_sioimath lhs, 733 unsigned long rhs) 734 { 735 isl_sioimath_scratchspace_t scratchlhs, scratchrhs; 736 int32_t smalllhs; 737 738 if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs <= UINT32_MAX)) { 739 isl_sioimath_set_int64(dst, (int64_t) smalllhs * (int64_t) rhs); 740 return; 741 } 742 743 mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs), 744 isl_sioimath_uiarg_src(rhs, &scratchrhs), 745 isl_sioimath_reinit_big(dst)); 746 isl_sioimath_try_demote(dst); 747 } 748 749 /* Compute the power of an isl_int to an unsigned long. 750 * Always let IMath do it; the result is unlikely to be small except in some 751 * special cases. 752 * Note: 0^0 == 1 753 */ 754 inline void isl_sioimath_pow_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, 755 unsigned long rhs) 756 { 757 isl_sioimath_scratchspace_t scratchlhs, scratchrhs; 758 int32_t smalllhs; 759 760 switch (rhs) { 761 case 0: 762 isl_sioimath_set_small(dst, 1); 763 return; 764 case 1: 765 isl_sioimath_set(dst, lhs); 766 return; 767 case 2: 768 isl_sioimath_mul(dst, lhs, lhs); 769 return; 770 } 771 772 if (isl_sioimath_decode_small(lhs, &smalllhs)) { 773 switch (smalllhs) { 774 case 0: 775 isl_sioimath_set_small(dst, 0); 776 return; 777 case 1: 778 isl_sioimath_set_small(dst, 1); 779 return; 780 case 2: 781 isl_sioimath_set_small(dst, 1); 782 isl_sioimath_mul_2exp(dst, *dst, rhs); 783 return; 784 default: 785 if ((MP_SMALL_MIN <= rhs) && (rhs <= MP_SMALL_MAX)) { 786 mp_int_expt_value(smalllhs, rhs, 787 isl_sioimath_reinit_big(dst)); 788 isl_sioimath_try_demote(dst); 789 return; 790 } 791 } 792 } 793 794 mp_int_expt_full(isl_sioimath_bigarg_src(lhs, &scratchlhs), 795 isl_sioimath_uiarg_src(rhs, &scratchrhs), 796 isl_sioimath_reinit_big(dst)); 797 isl_sioimath_try_demote(dst); 798 } 799 800 /* Fused multiply-add. 801 */ 802 inline void isl_sioimath_addmul(isl_sioimath_ptr dst, isl_sioimath_src lhs, 803 isl_sioimath_src rhs) 804 { 805 isl_sioimath tmp; 806 isl_sioimath_init(&tmp); 807 isl_sioimath_mul(&tmp, lhs, rhs); 808 isl_sioimath_add(dst, *dst, tmp); 809 isl_sioimath_clear(&tmp); 810 } 811 812 /* Fused multiply-add with an unsigned long. 813 */ 814 inline void isl_sioimath_addmul_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, 815 unsigned long rhs) 816 { 817 isl_sioimath tmp; 818 isl_sioimath_init(&tmp); 819 isl_sioimath_mul_ui(&tmp, lhs, rhs); 820 isl_sioimath_add(dst, *dst, tmp); 821 isl_sioimath_clear(&tmp); 822 } 823 824 /* Fused multiply-subtract. 825 */ 826 inline void isl_sioimath_submul(isl_sioimath_ptr dst, isl_sioimath_src lhs, 827 isl_sioimath_src rhs) 828 { 829 isl_sioimath tmp; 830 isl_sioimath_init(&tmp); 831 isl_sioimath_mul(&tmp, lhs, rhs); 832 isl_sioimath_sub(dst, *dst, tmp); 833 isl_sioimath_clear(&tmp); 834 } 835 836 /* Fused multiply-add with an unsigned long. 837 */ 838 inline void isl_sioimath_submul_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, 839 unsigned long rhs) 840 { 841 isl_sioimath tmp; 842 isl_sioimath_init(&tmp); 843 isl_sioimath_mul_ui(&tmp, lhs, rhs); 844 isl_sioimath_sub(dst, *dst, tmp); 845 isl_sioimath_clear(&tmp); 846 } 847 848 void isl_sioimath_gcd(isl_sioimath_ptr dst, isl_sioimath_src lhs, 849 isl_sioimath_src rhs); 850 void isl_sioimath_lcm(isl_sioimath_ptr dst, isl_sioimath_src lhs, 851 isl_sioimath_src rhs); 852 853 /* Divide lhs by rhs, rounding to zero (Truncate). 854 */ 855 inline void isl_sioimath_tdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs, 856 isl_sioimath_src rhs) 857 { 858 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 859 int32_t lhssmall, rhssmall; 860 861 if (isl_sioimath_decode_small(lhs, &lhssmall) && 862 isl_sioimath_decode_small(rhs, &rhssmall)) { 863 isl_sioimath_set_small(dst, lhssmall / rhssmall); 864 return; 865 } 866 867 mp_int_div(isl_sioimath_bigarg_src(lhs, &lhsscratch), 868 isl_sioimath_bigarg_src(rhs, &rhsscratch), 869 isl_sioimath_reinit_big(dst), NULL); 870 isl_sioimath_try_demote(dst); 871 return; 872 } 873 874 /* Divide lhs by an unsigned long rhs, rounding to zero (Truncate). 875 */ 876 inline void isl_sioimath_tdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, 877 unsigned long rhs) 878 { 879 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 880 int32_t lhssmall; 881 882 if (isl_sioimath_is_small(lhs) && (rhs <= (unsigned long) INT32_MAX)) { 883 lhssmall = isl_sioimath_get_small(lhs); 884 isl_sioimath_set_small(dst, lhssmall / (int32_t) rhs); 885 return; 886 } 887 888 if (rhs <= MP_SMALL_MAX) { 889 mp_int_div_value(isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs, 890 isl_sioimath_reinit_big(dst), NULL); 891 isl_sioimath_try_demote(dst); 892 return; 893 } 894 895 mp_int_div(isl_sioimath_bigarg_src(lhs, &lhsscratch), 896 isl_sioimath_uiarg_src(rhs, &rhsscratch), 897 isl_sioimath_reinit_big(dst), NULL); 898 isl_sioimath_try_demote(dst); 899 } 900 901 /* Divide lhs by rhs, rounding to positive infinity (Ceil). 902 */ 903 inline void isl_sioimath_cdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs, 904 isl_sioimath_src rhs) 905 { 906 int32_t lhssmall, rhssmall; 907 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 908 int32_t q; 909 910 if (isl_sioimath_decode_small(lhs, &lhssmall) && 911 isl_sioimath_decode_small(rhs, &rhssmall)) { 912 if ((lhssmall >= 0) && (rhssmall >= 0)) 913 q = ((int64_t) lhssmall + (int64_t) rhssmall - 1) / 914 rhssmall; 915 else if ((lhssmall < 0) && (rhssmall < 0)) 916 q = ((int64_t) lhssmall + (int64_t) rhssmall + 1) / 917 rhssmall; 918 else 919 q = lhssmall / rhssmall; 920 isl_sioimath_set_small(dst, q); 921 return; 922 } 923 924 impz_cdiv_q(isl_sioimath_reinit_big(dst), 925 isl_sioimath_bigarg_src(lhs, &lhsscratch), 926 isl_sioimath_bigarg_src(rhs, &rhsscratch)); 927 isl_sioimath_try_demote(dst); 928 } 929 930 /* Compute the division of lhs by a rhs of type unsigned long, rounding towards 931 * positive infinity (Ceil). 932 */ 933 inline void isl_sioimath_cdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, 934 unsigned long rhs) 935 { 936 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 937 int32_t lhssmall, q; 938 939 if (isl_sioimath_decode_small(lhs, &lhssmall) && (rhs <= INT32_MAX)) { 940 if (lhssmall >= 0) 941 q = ((int64_t) lhssmall + ((int64_t) rhs - 1)) / 942 (int64_t) rhs; 943 else 944 q = lhssmall / (int32_t) rhs; 945 isl_sioimath_set_small(dst, q); 946 return; 947 } 948 949 impz_cdiv_q(isl_sioimath_reinit_big(dst), 950 isl_sioimath_bigarg_src(lhs, &lhsscratch), 951 isl_sioimath_uiarg_src(rhs, &rhsscratch)); 952 isl_sioimath_try_demote(dst); 953 } 954 955 /* Divide lhs by rhs, rounding to negative infinity (Floor). 956 */ 957 inline void isl_sioimath_fdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs, 958 isl_sioimath_src rhs) 959 { 960 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 961 int32_t lhssmall, rhssmall; 962 int32_t q; 963 964 if (isl_sioimath_decode_small(lhs, &lhssmall) && 965 isl_sioimath_decode_small(rhs, &rhssmall)) { 966 if ((lhssmall < 0) && (rhssmall >= 0)) 967 q = ((int64_t) lhssmall - ((int64_t) rhssmall - 1)) / 968 rhssmall; 969 else if ((lhssmall >= 0) && (rhssmall < 0)) 970 q = ((int64_t) lhssmall - ((int64_t) rhssmall + 1)) / 971 rhssmall; 972 else 973 q = lhssmall / rhssmall; 974 isl_sioimath_set_small(dst, q); 975 return; 976 } 977 978 impz_fdiv_q(isl_sioimath_reinit_big(dst), 979 isl_sioimath_bigarg_src(lhs, &lhsscratch), 980 isl_sioimath_bigarg_src(rhs, &rhsscratch)); 981 isl_sioimath_try_demote(dst); 982 } 983 984 /* Compute the division of lhs by a rhs of type unsigned long, rounding towards 985 * negative infinity (Floor). 986 */ 987 inline void isl_sioimath_fdiv_q_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, 988 unsigned long rhs) 989 { 990 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 991 int32_t lhssmall, q; 992 993 if (isl_sioimath_decode_small(lhs, &lhssmall) && (rhs <= INT32_MAX)) { 994 if (lhssmall >= 0) 995 q = (uint32_t) lhssmall / rhs; 996 else 997 q = ((int64_t) lhssmall - ((int64_t) rhs - 1)) / 998 (int64_t) rhs; 999 isl_sioimath_set_small(dst, q); 1000 return; 1001 } 1002 1003 impz_fdiv_q(isl_sioimath_reinit_big(dst), 1004 isl_sioimath_bigarg_src(lhs, &lhsscratch), 1005 isl_sioimath_uiarg_src(rhs, &rhsscratch)); 1006 isl_sioimath_try_demote(dst); 1007 } 1008 1009 /* Get the remainder of: lhs divided by rhs rounded towards negative infinite 1010 * (Floor). 1011 */ 1012 inline void isl_sioimath_fdiv_r(isl_sioimath_ptr dst, isl_sioimath_src lhs, 1013 isl_sioimath_src rhs) 1014 { 1015 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 1016 int64_t lhssmall, rhssmall; 1017 int32_t r; 1018 1019 if (isl_sioimath_is_small(lhs) && isl_sioimath_is_small(rhs)) { 1020 lhssmall = isl_sioimath_get_small(lhs); 1021 rhssmall = isl_sioimath_get_small(rhs); 1022 r = (rhssmall + lhssmall % rhssmall) % rhssmall; 1023 isl_sioimath_set_small(dst, r); 1024 return; 1025 } 1026 1027 impz_fdiv_r(isl_sioimath_reinit_big(dst), 1028 isl_sioimath_bigarg_src(lhs, &lhsscratch), 1029 isl_sioimath_bigarg_src(rhs, &rhsscratch)); 1030 isl_sioimath_try_demote(dst); 1031 } 1032 1033 void isl_sioimath_read(isl_sioimath_ptr dst, const char *str); 1034 1035 /* Return: 1036 * +1 for a positive number 1037 * -1 for a negative number 1038 * 0 if the number is zero 1039 */ 1040 inline int isl_sioimath_sgn(isl_sioimath_src arg) 1041 { 1042 int32_t small; 1043 1044 if (isl_sioimath_decode_small(arg, &small)) 1045 return (small > 0) - (small < 0); 1046 1047 return mp_int_compare_zero(isl_sioimath_get_big(arg)); 1048 } 1049 1050 /* Return: 1051 * +1 if lhs > rhs 1052 * -1 if lhs < rhs 1053 * 0 if lhs = rhs 1054 */ 1055 inline int isl_sioimath_cmp(isl_sioimath_src lhs, isl_sioimath_src rhs) 1056 { 1057 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 1058 int32_t lhssmall, rhssmall; 1059 1060 if (isl_sioimath_decode_small(lhs, &lhssmall) && 1061 isl_sioimath_decode_small(rhs, &rhssmall)) 1062 return (lhssmall > rhssmall) - (lhssmall < rhssmall); 1063 1064 if (isl_sioimath_decode_small(rhs, &rhssmall)) 1065 return mp_int_compare_value( 1066 isl_sioimath_bigarg_src(lhs, &lhsscratch), rhssmall); 1067 1068 if (isl_sioimath_decode_small(lhs, &lhssmall)) 1069 return -mp_int_compare_value( 1070 isl_sioimath_bigarg_src(rhs, &rhsscratch), lhssmall); 1071 1072 return mp_int_compare( 1073 isl_sioimath_get_big(lhs), isl_sioimath_get_big(rhs)); 1074 } 1075 1076 /* As isl_sioimath_cmp, but with signed long rhs. 1077 */ 1078 inline int isl_sioimath_cmp_si(isl_sioimath_src lhs, signed long rhs) 1079 { 1080 int32_t lhssmall; 1081 1082 if (isl_sioimath_decode_small(lhs, &lhssmall)) 1083 return (lhssmall > rhs) - (lhssmall < rhs); 1084 1085 return mp_int_compare_value(isl_sioimath_get_big(lhs), rhs); 1086 } 1087 1088 /* Return: 1089 * +1 if |lhs| > |rhs| 1090 * -1 if |lhs| < |rhs| 1091 * 0 if |lhs| = |rhs| 1092 */ 1093 inline int isl_sioimath_abs_cmp(isl_sioimath_src lhs, isl_sioimath_src rhs) 1094 { 1095 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 1096 int32_t lhssmall, rhssmall; 1097 1098 if (isl_sioimath_decode_small(lhs, &lhssmall) && 1099 isl_sioimath_decode_small(rhs, &rhssmall)) { 1100 lhssmall = labs(lhssmall); 1101 rhssmall = labs(rhssmall); 1102 return (lhssmall > rhssmall) - (lhssmall < rhssmall); 1103 } 1104 1105 return mp_int_compare_unsigned( 1106 isl_sioimath_bigarg_src(lhs, &lhsscratch), 1107 isl_sioimath_bigarg_src(rhs, &rhsscratch)); 1108 } 1109 1110 /* Return whether lhs is divisible by rhs. 1111 * In particular, can rhs be multiplied by some integer to result in lhs? 1112 * If rhs is zero, then this means lhs has to be zero too. 1113 */ 1114 inline int isl_sioimath_is_divisible_by(isl_sioimath_src lhs, 1115 isl_sioimath_src rhs) 1116 { 1117 isl_sioimath_scratchspace_t lhsscratch, rhsscratch; 1118 int32_t lhssmall, rhssmall; 1119 mpz_t rem; 1120 int cmp; 1121 1122 if (isl_sioimath_sgn(rhs) == 0) 1123 return isl_sioimath_sgn(lhs) == 0; 1124 1125 if (isl_sioimath_decode_small(lhs, &lhssmall) && 1126 isl_sioimath_decode_small(rhs, &rhssmall)) 1127 return lhssmall % rhssmall == 0; 1128 1129 if (isl_sioimath_decode_small(rhs, &rhssmall)) 1130 return mp_int_divisible_value( 1131 isl_sioimath_bigarg_src(lhs, &lhsscratch), rhssmall); 1132 1133 mp_int_init(&rem); 1134 mp_int_div(isl_sioimath_bigarg_src(lhs, &lhsscratch), 1135 isl_sioimath_bigarg_src(rhs, &rhsscratch), NULL, &rem); 1136 cmp = mp_int_compare_zero(&rem); 1137 mp_int_clear(&rem); 1138 return cmp == 0; 1139 } 1140 1141 /* Return a hash code of an isl_sioimath. 1142 * The hash code for a number in small and big representation must be identical 1143 * on the same machine because small representation if not obligatory if fits. 1144 */ 1145 inline uint32_t isl_sioimath_hash(isl_sioimath_src arg, uint32_t hash) 1146 { 1147 int32_t small; 1148 int i; 1149 uint32_t num; 1150 mp_digit digits[(sizeof(uint32_t) + sizeof(mp_digit) - 1) / 1151 sizeof(mp_digit)]; 1152 mp_size used; 1153 const unsigned char *digitdata = (const unsigned char *) &digits; 1154 1155 if (isl_sioimath_decode_small(arg, &small)) { 1156 if (small < 0) 1157 isl_hash_byte(hash, 0xFF); 1158 num = labs(small); 1159 1160 isl_siomath_uint32_to_digits(num, digits, &used); 1161 for (i = 0; i < used * sizeof(mp_digit); i += 1) 1162 isl_hash_byte(hash, digitdata[i]); 1163 return hash; 1164 } 1165 1166 return isl_imath_hash(isl_sioimath_get_big(arg), hash); 1167 } 1168 1169 /* Return the number of digits in a number of the given base or more, i.e. the 1170 * string length without sign and null terminator. 1171 * 1172 * Current implementation for small representation returns the maximal number 1173 * of binary digits in that representation, which can be much larger than the 1174 * smallest possible solution. 1175 */ 1176 inline size_t isl_sioimath_sizeinbase(isl_sioimath_src arg, int base) 1177 { 1178 int32_t small; 1179 1180 if (isl_sioimath_decode_small(arg, &small)) 1181 return sizeof(int32_t) * CHAR_BIT - 1; 1182 1183 return impz_sizeinbase(isl_sioimath_get_big(arg), base); 1184 } 1185 1186 void isl_sioimath_print(FILE *out, isl_sioimath_src i, int width); 1187 void isl_sioimath_dump(isl_sioimath_src arg); 1188 1189 typedef isl_sioimath isl_int[1]; 1190 #define isl_int_init(i) isl_sioimath_init((i)) 1191 #define isl_int_clear(i) isl_sioimath_clear((i)) 1192 1193 #define isl_int_set(r, i) isl_sioimath_set((r), *(i)) 1194 #define isl_int_set_si(r, i) isl_sioimath_set_si((r), i) 1195 #define isl_int_set_ui(r, i) isl_sioimath_set_ui((r), i) 1196 #define isl_int_fits_slong(r) isl_sioimath_fits_slong(*(r)) 1197 #define isl_int_get_si(r) isl_sioimath_get_si(*(r)) 1198 #define isl_int_fits_ulong(r) isl_sioimath_fits_ulong(*(r)) 1199 #define isl_int_get_ui(r) isl_sioimath_get_ui(*(r)) 1200 #define isl_int_get_d(r) isl_sioimath_get_d(*(r)) 1201 #define isl_int_get_str(r) isl_sioimath_get_str(*(r)) 1202 #define isl_int_abs(r, i) isl_sioimath_abs((r), *(i)) 1203 #define isl_int_neg(r, i) isl_sioimath_neg((r), *(i)) 1204 #define isl_int_swap(i, j) isl_sioimath_swap((i), (j)) 1205 #define isl_int_swap_or_set(i, j) isl_sioimath_swap((i), (j)) 1206 #define isl_int_add_ui(r, i, j) isl_sioimath_add_ui((r), *(i), j) 1207 #define isl_int_sub_ui(r, i, j) isl_sioimath_sub_ui((r), *(i), j) 1208 1209 #define isl_int_add(r, i, j) isl_sioimath_add((r), *(i), *(j)) 1210 #define isl_int_sub(r, i, j) isl_sioimath_sub((r), *(i), *(j)) 1211 #define isl_int_mul(r, i, j) isl_sioimath_mul((r), *(i), *(j)) 1212 #define isl_int_mul_2exp(r, i, j) isl_sioimath_mul_2exp((r), *(i), j) 1213 #define isl_int_mul_si(r, i, j) isl_sioimath_mul_si((r), *(i), j) 1214 #define isl_int_mul_ui(r, i, j) isl_sioimath_mul_ui((r), *(i), j) 1215 #define isl_int_pow_ui(r, i, j) isl_sioimath_pow_ui((r), *(i), j) 1216 #define isl_int_addmul(r, i, j) isl_sioimath_addmul((r), *(i), *(j)) 1217 #define isl_int_addmul_ui(r, i, j) isl_sioimath_addmul_ui((r), *(i), j) 1218 #define isl_int_submul(r, i, j) isl_sioimath_submul((r), *(i), *(j)) 1219 #define isl_int_submul_ui(r, i, j) isl_sioimath_submul_ui((r), *(i), j) 1220 1221 #define isl_int_gcd(r, i, j) isl_sioimath_gcd((r), *(i), *(j)) 1222 #define isl_int_lcm(r, i, j) isl_sioimath_lcm((r), *(i), *(j)) 1223 #define isl_int_divexact(r, i, j) isl_sioimath_tdiv_q((r), *(i), *(j)) 1224 #define isl_int_divexact_ui(r, i, j) isl_sioimath_tdiv_q_ui((r), *(i), j) 1225 #define isl_int_tdiv_q(r, i, j) isl_sioimath_tdiv_q((r), *(i), *(j)) 1226 #define isl_int_cdiv_q(r, i, j) isl_sioimath_cdiv_q((r), *(i), *(j)) 1227 #define isl_int_cdiv_q_ui(r, i, j) isl_sioimath_cdiv_q_ui((r), *(i), j) 1228 #define isl_int_fdiv_q(r, i, j) isl_sioimath_fdiv_q((r), *(i), *(j)) 1229 #define isl_int_fdiv_r(r, i, j) isl_sioimath_fdiv_r((r), *(i), *(j)) 1230 #define isl_int_fdiv_q_ui(r, i, j) isl_sioimath_fdiv_q_ui((r), *(i), j) 1231 1232 #define isl_int_read(r, s) isl_sioimath_read((r), s) 1233 #define isl_int_sgn(i) isl_sioimath_sgn(*(i)) 1234 #define isl_int_cmp(i, j) isl_sioimath_cmp(*(i), *(j)) 1235 #define isl_int_cmp_si(i, si) isl_sioimath_cmp_si(*(i), si) 1236 #define isl_int_eq(i, j) (isl_sioimath_cmp(*(i), *(j)) == 0) 1237 #define isl_int_ne(i, j) (isl_sioimath_cmp(*(i), *(j)) != 0) 1238 #define isl_int_lt(i, j) (isl_sioimath_cmp(*(i), *(j)) < 0) 1239 #define isl_int_le(i, j) (isl_sioimath_cmp(*(i), *(j)) <= 0) 1240 #define isl_int_gt(i, j) (isl_sioimath_cmp(*(i), *(j)) > 0) 1241 #define isl_int_ge(i, j) (isl_sioimath_cmp(*(i), *(j)) >= 0) 1242 #define isl_int_abs_cmp(i, j) isl_sioimath_abs_cmp(*(i), *(j)) 1243 #define isl_int_abs_eq(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) == 0) 1244 #define isl_int_abs_ne(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) != 0) 1245 #define isl_int_abs_lt(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) < 0) 1246 #define isl_int_abs_gt(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) > 0) 1247 #define isl_int_abs_ge(i, j) (isl_sioimath_abs_cmp(*(i), *(j)) >= 0) 1248 #define isl_int_is_divisible_by(i, j) isl_sioimath_is_divisible_by(*(i), *(j)) 1249 1250 #define isl_int_hash(v, h) isl_sioimath_hash(*(v), h) 1251 #define isl_int_free_str(s) free(s) 1252 #define isl_int_print(out, i, width) isl_sioimath_print(out, *(i), width) 1253 1254 #endif /* ISL_INT_SIOIMATH_H */ 1255