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
73typedef uint64_t isl_sioimath;
74#else
75typedef 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. */
95typedef isl_sioimath *isl_sioimath_ptr;
96
97/* Used for function parameters that are read-only. */
98typedef isl_sioimath isl_sioimath_src;
99
100/* Return whether the argument is stored in small representation.
101 */
102inline 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 */
109inline 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 */
117inline 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 */
125inline 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 */
136inline 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 */
144inline 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 */
152inline 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 */
159inline 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 */
186typedef 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
220inline 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
226inline 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
232inline 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 */
247inline 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 */
274inline 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 */
295inline 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 */
316inline 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 */
331inline 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 */
340inline 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 */
349inline 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 */
361inline 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 */
375inline 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 */
389inline 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 */
405inline 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 */
412inline 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 */
422inline 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 */
434inline 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 */
446inline 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 */
458inline 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 */
471inline 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 */
484inline 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 */
497inline 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 */
510inline 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 */
535inline 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 */
550inline 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 */
562inline 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 */
577inline 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 */
589inline 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 */
612inline 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 */
631inline 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 */
652inline 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 */
673inline 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 */
695inline 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 */
712inline 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 */
732inline 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 */
754inline 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 */
802inline 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 */
814inline 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 */
826inline 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 */
838inline 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
848void isl_sioimath_gcd(isl_sioimath_ptr dst, isl_sioimath_src lhs,
849		      isl_sioimath_src rhs);
850void 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 */
855inline 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 */
876inline 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 */
903inline 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 */
933inline 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 */
957inline 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 */
987inline 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 */
1012inline 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
1033void 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 */
1040inline 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 */
1055inline 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 */
1078inline 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 */
1093inline 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 */
1114inline 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 */
1145inline 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 */
1176inline 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
1186void isl_sioimath_print(FILE *out, isl_sioimath_src i, int width);
1187void isl_sioimath_dump(isl_sioimath_src arg);
1188
1189typedef 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