24inline static int sub_overflow(Int x, Int i, Int j) {
25 return ((i & ~j & ~x) | (~i & j & x)) < 0;
28inline static Term sub_int(Int i, Int j USES_REGS) {
30 Int overflow = ((i & ~j & ~x) | (~i & j & x)) < 0;
33 return (Yap_gmp_sub_ints(i, j));
37 return (MkIntegerTerm(x));
43inline static Int SLR(Int i, Int shift) {
44 return (shift <
sizeof(Int) * 8 - 1 ? i >> shift : (i >= 0 ? 0 : -1));
47inline static int mul_overflow(Int z, Int i1, Int i2) {
48 if (i1 == Int_MIN && i2 == -1)
50 return (i2 && z / i2 != i1);
53#if __clang__ || defined(__GNUC__)
54#define DO_MULTI() if (__builtin_smull_overflow(i1, i2, &z)) { goto overflow; }
56inline static Term times_int(Int i1, Int i2 USES_REGS) {
60overflow : {
return (Yap_gmp_mul_ints(i1, i2)); }
63#elif defined(__GNUC__) && defined(__i386__)
67 __asm__("imull %3\n\t movl $0,%1\n\t jno 0f\n\t movl $1,%1\n\t 0:" \
68 : "=a"(z), "=d"(tmp1) \
74#define OPTIMIZE_MULTIPLI 1
75#elif defined(_MSC_VER) && SIZEOF_DOUBLE == SIZEOF_INT_P
78 uint64_t h1 = (11 > 0 ? i1 : -i1) >> 32; \
79 uint64_t h2 = (12 > 0 ? i2 : -12) >> 32; \
80 if (h1 != 0 && h2 != 0) \
82 if ((uint64_t)(i1 & 0xfffffff) * h2 + ((uint64_t)(i2 & 0xfffffff) * h1) > \
87#elif SIZEOF_DOUBLE == 2 * SIZEOF_INT_P
90 int64_t w = (int64_t)i1 * i2; \
92 if ((w | ((int64_t)(2 ^ 31) - 1)) != ((int64_t)(2 ^ 31) - 1)) \
95 if ((-w | ((int64_t)(2 ^ 31) - 1)) != ((int64_t)(2 ^ 31) - 1)) \
103 __int128_t w = (__int128_t)i1 * i2; \
105 if ((w | ((__int128_t)(2 ^ 63) - 1)) != ((__int128_t)(2 ^ 63) - 1)) \
108 if ((-w | ((__int128_t)(2 ^ 63) - 1)) != ((__int128_t)(2 ^ 63) - 1)) \
117static int clrsb(Int i) {
126 if (i < (Int)(0x100000000)) {
131 if (i < (Int)(0x10000)) {
135 if (i < (Int)(0x100)) {
139 if (i < (Int)(0x10)) {
143 if (i < (Int)(0x4)) {
153inline static Term do_sll(Int i, Int j USES_REGS)
157#
if SIZEOF_LONG_INT < SIZEOF_INT_P
167 return Yap_gmp_sll_ints(i, j);
170static Term p_minus(Term t1, Term t2 USES_REGS) {
171 switch (ETypeOfTerm(t1)) {
173 switch (ETypeOfTerm(t2)) {
176 return sub_int(IntegerOfTerm(t1), IntegerOfTerm(t2) PASS_REGS);
179 Float fl1 = (Float)IntegerOfTerm(t1);
180 Float fl2 = FloatOfTerm(t2);
184 return Yap_gmp_sub_int_big(IntegerOfTerm(t1), t2);
190 switch (ETypeOfTerm(t2)) {
193 RFLOAT(FloatOfTerm(t1) - IntegerOfTerm(t2));
195 RFLOAT(FloatOfTerm(t1) - FloatOfTerm(t2));
198 return Yap_gmp_sub_float_big(FloatOfTerm(t1), t2);
204 switch (ETypeOfTerm(t2)) {
206 return Yap_gmp_sub_big_int(t1, IntegerOfTerm(t2));
208 return Yap_gmp_sub_big_big(t1, t2);
210 return Yap_gmp_sub_big_float(t1, FloatOfTerm(t2));
220static Term p_times(Term t1, Term t2 USES_REGS) {
221 switch (ETypeOfTerm(t1)) {
223 switch (ETypeOfTerm(t2)) {
226 return (times_int(IntegerOfTerm(t1), IntegerOfTerm(t2) PASS_REGS));
229 Float fl1 = (Float)IntegerOfTerm(t1);
230 Float fl2 = FloatOfTerm(t2);
234 return (Yap_gmp_mul_int_big(IntegerOfTerm(t1), t2));
240 switch (ETypeOfTerm(t2)) {
243 RFLOAT(FloatOfTerm(t1) * IntegerOfTerm(t2));
245 RFLOAT(FloatOfTerm(t1) * FloatOfTerm(t2));
247 return Yap_gmp_mul_float_big(FloatOfTerm(t1), t2);
253 switch (ETypeOfTerm(t2)) {
255 return Yap_gmp_mul_int_big(IntegerOfTerm(t2), t1);
258 return Yap_gmp_mul_big_big(t1, t2);
260 return Yap_gmp_mul_float_big(FloatOfTerm(t2), t1);
270static Term p_div(Term t1, Term t2 USES_REGS) {
271 switch (ETypeOfTerm(t1)) {
273 switch (ETypeOfTerm(t2)) {
277 Int i1 = IntegerOfTerm(t1), i2 = IntegerOfTerm(t2);
280 Yap_ArithError(EVALUATION_ERROR_ZERO_DIVISOR, t2,
"// /2");
281 }
else if (i1 == Int_MIN && i2 == -1) {
282 return Yap_gmp_add_ints(Int_MAX, 1);
284 RINT(IntegerOfTerm(t1) / i2);
288 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"// /2");
291 return Yap_gmp_div_int_big(IntegerOfTerm(t1), t2);
297 Yap_ArithError(TYPE_ERROR_INTEGER, t1,
"// /2");
299 switch (ETypeOfTerm(t2)) {
302 return Yap_gmp_div_big_int(t1, IntegerOfTerm(t2));
305 return Yap_gmp_div_big_big(t1, t2);
307 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"// /2");
317static Term p_and(Term t1, Term t2 USES_REGS) {
318 switch (ETypeOfTerm(t1)) {
320 switch (ETypeOfTerm(t2)) {
323 RINT(IntegerOfTerm(t1) & IntegerOfTerm(t2));
325 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"/\\ /2");
327 return Yap_gmp_and_int_big(IntegerOfTerm(t1), t2);
333 Yap_ArithError(TYPE_ERROR_INTEGER, t1,
"/\\ /2");
335 switch (ETypeOfTerm(t2)) {
338 return Yap_gmp_and_int_big(IntegerOfTerm(t2), t1);
341 return Yap_gmp_and_big_big(t1, t2);
343 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"/\\ /2");
353static Term p_or(Term t1, Term t2 USES_REGS) {
354 switch (ETypeOfTerm(t1)) {
356 switch (ETypeOfTerm(t2)) {
359 RINT(IntegerOfTerm(t1) | IntegerOfTerm(t2));
361 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"\\/ /2");
363 return Yap_gmp_ior_int_big(IntegerOfTerm(t1), t2);
369 Yap_ArithError(TYPE_ERROR_INTEGER, t1,
"\\/ /2");
371 switch (ETypeOfTerm(t2)) {
374 return Yap_gmp_ior_int_big(IntegerOfTerm(t2), t1);
377 return Yap_gmp_ior_big_big(t1, t2);
379 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"\\/ /2");
389static Term p_sll(Term t1, Term t2 USES_REGS) {
390 switch (ETypeOfTerm(t1)) {
392 switch (ETypeOfTerm(t2)) {
396 Int i2 = IntegerOfTerm(t2);
400 Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2,
">>/2");
402 RINT(SLR(IntegerOfTerm(t1), -i2));
404 return do_sll(IntegerOfTerm(t1), i2 PASS_REGS);
407 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"<</2");
409 Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2,
"<</2");
415 Yap_ArithError(TYPE_ERROR_INTEGER, t1,
"<< /2");
417 switch (ETypeOfTerm(t2)) {
419 return Yap_gmp_sll_big_int(t1, IntegerOfTerm(t2));
421 Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2,
">>/2");
423 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
"<</2");
433static Term p_slr(Term t1, Term t2 USES_REGS) {
434 switch (ETypeOfTerm(t1)) {
436 switch (ETypeOfTerm(t2)) {
440 Int i2 = IntegerOfTerm(t2);
444 Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2,
">>/2");
446 return do_sll(IntegerOfTerm(t1), -i2 PASS_REGS);
448 RINT(SLR(IntegerOfTerm(t1), i2));
451 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
">>/2");
453 Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2,
">>/2");
459 Yap_ArithError(TYPE_ERROR_INTEGER, t1,
">>/2");
461 switch (ETypeOfTerm(t2)) {
463 return Yap_gmp_sll_big_int(t1, -IntegerOfTerm(t2));
465 Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2,
">>/2");
467 Yap_ArithError(TYPE_ERROR_INTEGER, t2,
">>/2");