int fmpq_get_mpfr(mpfr_t r, const fmpq_t x, mpfr_rnd_t rnd) { __mpq_struct mpq; fmpz p, q; mp_limb_t pp, qq; p = *fmpq_numref(x); q = *fmpq_denref(x); if (p == 0) return mpfr_set_ui(r, 0, rnd); if (COEFF_IS_MPZ(p)) mpq._mp_num = *COEFF_TO_PTR(p); else { pp = FLINT_ABS(p); mpq._mp_num._mp_alloc = 1; mpq._mp_num._mp_size = (p < 0) ? -1 : 1; mpq._mp_num._mp_d = &pp; } if (COEFF_IS_MPZ(q)) mpq._mp_den = *COEFF_TO_PTR(q); else { qq = q; mpq._mp_den._mp_alloc = 1; mpq._mp_den._mp_size = 1; mpq._mp_den._mp_d = &qq; } return mpfr_set_q(r, &mpq, rnd); }
void fmpz_tdiv_qr(fmpz_t f, fmpz_t s, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_printf("Exception: division by zero in fmpz_tdiv_qr\n"); abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ fmpz_set_si(f, q); fmpz_set_si(s, r); } else /* h is large and g is small */ { fmpz_set_ui(f, WORD(0)); /* g is zero */ fmpz_set_si(s, c1); } } else /* g is large */ { __mpz_struct *mpz_ptr, *mpz_ptr2; _fmpz_promote(f); /* must not hang on to ptr whilst promoting s */ mpz_ptr2 = _fmpz_promote(s); mpz_ptr = COEFF_TO_PTR(*f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_tdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), c2); } else { flint_mpz_tdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_tdiv_qr(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ _fmpz_demote_val(s); /* division by h may result in small value */ } }
void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { printf("Exception: division by zero in fmpz_fdiv_q\n"); abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if (r && (c2 ^ r) < 0L) --q; fmpz_set_si(f, q); } else /* h is large and g is small */ { if ((c1 > 0L && fmpz_sgn(h) < 0) || (c1 < 0L && fmpz_sgn(h) > 0)) /* signs are the same */ fmpz_set_si(f, -1L); /* quotient is negative, round down to minus one */ else fmpz_zero(f); } } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_fdiv_q(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ } }
int fmpz_fits_si(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) { return 1; } else { #if defined(_WIN64) return flint_mpz_fits_si_p(COEFF_TO_PTR(*f)); #else return mpz_fits_slong_p(COEFF_TO_PTR(*f)); #endif } }
int fmpz_fprint(FILE * file, const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) return fprintf(file, "%ld", *x); else return (int) mpz_out_str(file, 10, COEFF_TO_PTR(*x)); }
void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mpz_ptr = COEFF_TO_PTR(*f); long size = mpz_ptr->_mp_size; if (size == 0L) /* value is zero */ { _fmpz_clear_mpz(*f); (*f) = 0; } else if (size == 1L) /* value is positive and 1 limb */ { ulong uval = mpz_get_ui(mpz_ptr); if (uval <= (ulong) COEFF_MAX) { _fmpz_clear_mpz(*f); (*f) = (fmpz) uval; } } else if (size == -1L) /* value is negative and 1 limb */ { ulong uval = mpz_get_ui(mpz_ptr); if (uval <= (ulong) COEFF_MAX) { _fmpz_clear_mpz(*f); (*f) = (fmpz) -uval; } } /* don't do anything if value has to be multi precision */ }
void fmpz_tdiv_q_ui(fmpz_t f, const fmpz_t g, ulong h) { fmpz c1 = *g; ulong c2 = h; if (h == 0) { printf("Exception: division by zero in fmpz_tdiv_q_ui\n"); abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 > 0) { fmpz_set_ui(f, c1 / c2); } else { ulong q = ((ulong) -c1) / c2; fmpz_set_si(f, - (long) q); } } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_tdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } }
ulong fmpz_fdiv_ui(const fmpz_t g, ulong h) { fmpz c1 = *g; ulong r; if (h == 0UL) { printf("Exception: division by 0 in fmpz_fdiv_ui\n"); abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (c1 < 0L) { r = h - (-c1 % h); /* C doesn't correctly handle negative mods */ if (r == h) r = 0; } else r = c1 % h; return r; } else /* g is large */ { return mpz_fdiv_ui(COEFF_TO_PTR(c1), h); } }
int fmpr_get_mpfr(mpfr_t x, const fmpr_t y, mpfr_rnd_t rnd) { int r; if (fmpr_is_special(y)) { if (fmpr_is_zero(y)) mpfr_set_zero(x, 0); else if (fmpr_is_pos_inf(y)) mpfr_set_inf(x, 1); else if (fmpr_is_neg_inf(y)) mpfr_set_inf(x, -1); else mpfr_set_nan(x); r = 0; } else if (COEFF_IS_MPZ(*fmpr_expref(y))) { flint_printf("exception: exponent too large to convert to mpfr"); abort(); } else { if (!COEFF_IS_MPZ(*fmpr_manref(y))) #if defined(__MINGW64__) r = mpfr_set_sj_2exp(x, *fmpr_manref(y), *fmpr_expref(y), rnd); #else r = mpfr_set_si_2exp(x, *fmpr_manref(y), *fmpr_expref(y), rnd); #endif else r = mpfr_set_z_2exp(x, COEFF_TO_PTR(*fmpr_manref(y)), *fmpr_expref(y), rnd); if (!mpfr_regular_p(x)) { flint_printf("exception: exponent too large to convert to mpfr"); abort(); } }
void fmpz_gcd(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(g)) { fmpz_abs(f, h); return; } if (fmpz_is_zero(h)) { fmpz_abs(f, g); return; } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz_set_si(f, z_gcd(c1, c2)); } else /* h is large, but g is small */ { fmpz c2d = fmpz_fdiv_ui(h, FLINT_ABS(c1)); fmpz_set_si(f, z_gcd(c1, c2d)); } } else { if (!COEFF_IS_MPZ(c2)) /* h is small, but g is large */ { fmpz c1d = fmpz_fdiv_ui(g, FLINT_ABS(c2)); fmpz_set_si(f, z_gcd(c2, c1d)); } else /* g and h are both large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* aliasing fine as g, h already large */ mpz_gcd(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* gcd may be small */ } } }
void fmpz_divexact(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { flint_printf("Exception (fmpz_divexact). Division by zero.\n"); abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small, h must be also or division isn't exact */ { fmpz_set_si(f, c1 / c2); } else /* g is large */ { __mpz_struct * mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); _fmpz_demote_val(f); /* division by h may result in small value */ } else { flint_mpz_divexact_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); _fmpz_demote_val(f); /* division by h may result in small value */ fmpz_neg(f, f); } } else /* both are large */ { mpz_divexact(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); _fmpz_demote_val(f); /* division by h may result in small value */ } } }
int fmpz_fits_si(const fmpz_t f) { if (!COEFF_IS_MPZ(*f)) { return 1; } else { return mpz_fits_slong_p(COEFF_TO_PTR(*f)); } }
void flint_mpz_init_set_readonly(mpz_t z, const fmpz_t f) { if (COEFF_IS_MPZ(*f)) { *z = *COEFF_TO_PTR(*f); } else { mpz_init_set_si(z, *f); } }
__mpz_struct * _fmpz_promote(fmpz_t f) { if (!COEFF_IS_MPZ(*f)) /* f is small so promote it first */ { __mpz_struct * mpz_ptr = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mpz_ptr); return mpz_ptr; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(*f); }
int fmpz_cmpabs(const fmpz_t f, const fmpz_t g) { if (f == g) return 0; /* aliased inputs */ if (!COEFF_IS_MPZ(*f)) { if (!COEFF_IS_MPZ(*g)) { mp_limb_t uf = FLINT_ABS(*f); mp_limb_t ug = FLINT_ABS(*g); return (uf < ug ? -1 : (uf > ug)); } else return -1; } else { if (!COEFF_IS_MPZ(*g)) return 1; /* f is large, so if g isn't... */ else return mpz_cmpabs(COEFF_TO_PTR(*f), COEFF_TO_PTR(*g)); } }
double fmpz_dlog(const fmpz_t x) { if (!COEFF_IS_MPZ(*x)) { return log(*x); } else { double s; slong e; #if defined(__MPIR_VERSION) s = mpz_get_d_2exp(&e, COEFF_TO_PTR(*x)); #else s = mpz_get_d_2exp((long *) &e, COEFF_TO_PTR(*x)); #endif return log(s) + e * 0.69314718055994530942; } }
mp_size_t fmpz_size(const fmpz_t f) { fmpz d = *f; if (d == 0) return 0; if (!COEFF_IS_MPZ(d)) return 1; else return mpz_size(COEFF_TO_PTR(d)); }
__mpz_struct * _fmpz_promote_val(fmpz_t f) { fmpz c = (*f); if (!COEFF_IS_MPZ(c)) /* f is small so promote it */ { __mpz_struct * mpz_ptr = _fmpz_new_mpz(); (*f) = PTR_TO_COEFF(mpz_ptr); mpz_set_si(mpz_ptr, c); return mpz_ptr; } else /* f is large already, just return the pointer */ return COEFF_TO_PTR(c); }
void fmpz_add(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* both inputs are small */ { fmpz_set_si(f, c1 + c2); } else /* g is small, h is large */ { __mpz_struct * mpz3 = _fmpz_promote(f); /* g is saved and h is large */ __mpz_struct * mpz2 = COEFF_TO_PTR(c2); if (c1 < 0L) mpz_sub_ui(mpz3, mpz2, -c1); else mpz_add_ui(mpz3, mpz2, c1); _fmpz_demote_val(f); /* may have cancelled */ } } else { if (!COEFF_IS_MPZ(c2)) /* g is large, h is small */ { __mpz_struct * mpz3 = _fmpz_promote(f); /* h is saved and g is large */ __mpz_struct * mpz1 = COEFF_TO_PTR(c1); if (c2 < 0L) mpz_sub_ui(mpz3, mpz1, -c2); else mpz_add_ui(mpz3, mpz1, c2); _fmpz_demote_val(f); /* may have cancelled */ } else /* g and h are large */ { __mpz_struct * mpz3 = _fmpz_promote(f); /* aliasing means f is already large */ __mpz_struct * mpz1 = COEFF_TO_PTR(c1); __mpz_struct * mpz2 = COEFF_TO_PTR(c2); mpz_add(mpz3, mpz1, mpz2); _fmpz_demote_val(f); /* may have cancelled */ } } }
static __inline__ int low_bits_are_zero(const fmpz_t u, int bits) { fmpz f = *u; mp_limb_t low; if (!COEFF_IS_MPZ(f)) low = FLINT_ABS(f); else low = COEFF_TO_PTR(f)->_mp_d[0]; return (low & ((UWORD(1) << bits) - 1)) == 0; }
int fmpz_cmp_ui(const fmpz_t f, ulong g) { fmpz c = *f; if (!COEFF_IS_MPZ(c)) /* f is small */ { if (c < 0L || g > COEFF_MAX) return -1; else return c < (long) g ? -1 : c > (long) g; } else /* f is large */ return mpz_cmp_ui(COEFF_TO_PTR(c), g); }
void fmpz_powm(fmpz_t f, const fmpz_t g, const fmpz_t e, const fmpz_t m) { if (fmpz_sgn(m) <= 0) { flint_printf("Exception (fmpz_powm). Modulus is less than 1.\n"); abort(); } else if (!COEFF_IS_MPZ(*e)) /* e is small */ { fmpz_powm_ui(f, g, *e, m); } else /* e is large */ { if (!COEFF_IS_MPZ(*m)) /* m is small */ { ulong g1 = fmpz_fdiv_ui(g, *m); mpz_t g2, m2; __mpz_struct *mpz_ptr; flint_mpz_init_set_ui(g2, g1); flint_mpz_init_set_ui(m2, *m); mpz_ptr = _fmpz_promote(f); mpz_powm(mpz_ptr, g2, COEFF_TO_PTR(*e), m2); mpz_clear(g2); mpz_clear(m2); _fmpz_demote_val(f); } else /* m is large */ { if (!COEFF_IS_MPZ(*g)) /* g is small */ { mpz_t g2; __mpz_struct *mpz_ptr; flint_mpz_init_set_si(g2, *g); mpz_ptr = _fmpz_promote(f); mpz_powm(mpz_ptr, g2, COEFF_TO_PTR(*e), COEFF_TO_PTR(*m)); mpz_clear(g2); _fmpz_demote_val(f); } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_powm(mpz_ptr, COEFF_TO_PTR(*g), COEFF_TO_PTR(*e), COEFF_TO_PTR(*m)); _fmpz_demote_val(f); } } } }
void fmpz_sub_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz c = *g; if (!COEFF_IS_MPZ(c)) /* coeff is small */ { mp_limb_t sum[2]; if (c < 0L) /* g negative, x positive, so difference is negative */ { add_ssaaaa(sum[1], sum[0], 0, -c, 0, x); if (sum[1] == 0) { fmpz_set_ui(f, sum[0]); /* result fits in 1 limb */ fmpz_neg(f, f); } else /* result takes two limbs */ { __mpz_struct * mpz_ptr; mpz_t temp; temp->_mp_d = sum; temp->_mp_size = -2; /* result is negative number minus negative number, hence negative */ mpz_ptr = _fmpz_promote(f); /* g has already been read */ mpz_set(mpz_ptr, temp); } } else /* coeff is non-negative, x non-negative */ { if (x < c) fmpz_set_ui(f, c - x); /* won't be negative and is smaller than c */ else { fmpz_set_ui(f, x - c); /* positive or zero */ fmpz_neg(f, f); } } } else { __mpz_struct *mpz_ptr, *mpz_ptr2; mpz_ptr = COEFF_TO_PTR(c); mpz_ptr2 = _fmpz_promote(f); /* g is already large */ mpz_sub_ui(mpz_ptr2, mpz_ptr, x); _fmpz_demote_val(f); /* cancellation may have occurred */ } }
void fmpz_set(fmpz_t f, const fmpz_t g) { if (f == g) return; /* aliased inputs */ if (!COEFF_IS_MPZ(*g)) /* g is small */ { _fmpz_demote(f); *f = *g; } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); mpz_set(mpz_ptr, COEFF_TO_PTR(*g)); } }
void fmpz_clrbit(fmpz_t f, ulong i) { if (!COEFF_IS_MPZ(*f)) { if (i < FLINT_BITS - 2) { *f &= ~(WORD(1) << i); } /* i >= FLINT_BITS --> nop */ } else { __mpz_struct *ptr = COEFF_TO_PTR(*f); mpz_clrbit(ptr, i); _fmpz_demote_val(f); } }
void fmpz_mul_si(fmpz_t f, const fmpz_t g, long x) { fmpz c2 = *g; if (x == 0) { fmpz_zero(f); return; } else if (!COEFF_IS_MPZ(c2)) /* c2 is small */ { mp_limb_t prod[2]; mp_limb_t uc2 = FLINT_ABS(c2); mp_limb_t ux = FLINT_ABS(x); /* unsigned limb by limb multiply (assembly for most CPU's) */ umul_ppmm(prod[1], prod[0], uc2, ux); if (!prod[1]) /* result fits in one limb */ { fmpz_set_ui(f, prod[0]); if ((c2 ^ x) < 0L) fmpz_neg(f, f); } else /* result takes two limbs */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* two limbs, least significant first, native endian, no nails, stored in prod */ mpz_import(mpz_ptr, 2, -1, sizeof(mp_limb_t), 0, 0, prod); if ((c2 ^ x) < 0L) mpz_neg(mpz_ptr, mpz_ptr); } } else /* c2 is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); /* ok without val as if aliased both are large */ mpz_mul_si(mpz_ptr, COEFF_TO_PTR(c2), x); } }
void _fmpz_demote_val(fmpz_t f) { __mpz_struct * mpz_ptr = COEFF_TO_PTR(*f); int size = mpz_ptr->_mp_size; if (!(((unsigned int) size + 1U) & ~2U)) /* size +-1 */ { ulong uval = mpz_ptr->_mp_d[0]; if (uval <= (ulong) COEFF_MAX) { _fmpz_clear_mpz(*f); *f = size * (fmpz) uval; } } else if (size == 0) /* value is 0 */ { _fmpz_clear_mpz(*f); *f = 0; } /* don't do anything if value has to be multi precision */ }
/* Divide (arrayg, limbsg) by the positive value gc inplace and return the number of limbs written */ mp_size_t mpn_tdiv_q_fmpz_inplace(mp_ptr arrayg, mp_size_t limbsg, fmpz_t gc) { if (fmpz_size(gc) == 1) { mpn_divmod_1(arrayg, arrayg, limbsg, fmpz_get_ui(gc)); return limbsg - (arrayg[limbsg - 1] == 0); } else { mp_size_t tlimbs; __mpz_struct * mpz_ptr = COEFF_TO_PTR(*gc); mp_ptr temp = flint_malloc(limbsg*sizeof(mp_limb_t)); mpn_copyi(temp, arrayg, limbsg); mpn_tdiv_q(arrayg, temp, limbsg, mpz_ptr->_mp_d, mpz_ptr->_mp_size); tlimbs = limbsg - mpz_ptr->_mp_size + 1; tlimbs -= (arrayg[tlimbs - 1] == 0); flint_free(temp); return tlimbs; } }
char * _fmpz_poly_get_str_pretty(const fmpz * poly, long len, const char *x) { char *str; size_t off; long i, bound, nz; if (len == 0) { str = flint_malloc(2); str[0] = '0'; str[1] = '\0'; return str; } if (len == 1) { str = fmpz_get_str(NULL, 10, poly); return str; } nz = 0; bound = 1; for (i = 0; i < len; i++) if (!fmpz_is_zero(poly + i)) { bound += fmpz_sizeinbase(poly + i, 10) + 1; nz++; } bound += nz * (3 + strlen(x) + (long) (ceil(log10(len)))); str = flint_malloc(bound); off = 0; i = len - 1; if (poly[i] == 1L) { } else if (poly[i] == -1L) str[off++] = '-'; else if (!COEFF_IS_MPZ(poly[i])) off += sprintf(str + off, "%ld*", poly[i]); else off += gmp_sprintf(str + off, "%Zd*", COEFF_TO_PTR(poly[i])); if (i > 1) off += sprintf(str + off, "%s^%ld", x, i); else off += sprintf(str + off, "%s", x); for (--i; i > 0; --i) { if (poly[i] == 0L) continue; if (fmpz_sgn(poly + i) > 0) str[off++] = '+'; if (poly[i] == -1L) str[off++] = '-'; if (poly[i] != 1L && poly[i] != -1L) { if (!COEFF_IS_MPZ(poly[i])) off += sprintf(str + off, "%ld*", poly[i]); else off += gmp_sprintf(str + off, "%Zd*", COEFF_TO_PTR(poly[i])); } if (i > 1) off += sprintf(str + off, "%s^%ld", x, i); else off += sprintf(str + off, "%s", x); } if (poly[i] != 0L) { if (fmpz_sgn(poly + i) > 0) str[off++] = '+'; if (!COEFF_IS_MPZ(poly[i])) off += sprintf(str + off, "%ld", poly[i]); else off += gmp_sprintf(str + off, "%Zd", COEFF_TO_PTR(poly[i])); } return str; }
void fmpz_addmul_ui(fmpz_t f, const fmpz_t g, ulong x) { fmpz c1, r; c1 = *g; if ((x == 0) || (c1 == 0)) /* product is zero */ return; r = *f; if (r == 0) { fmpz_mul_ui(f, g, x); /* we are adding product to 0 */ return; } if (x == UWORD(1)) /* special case, adding g*1 to f */ { fmpz_add(f, f, g); return; } if (c1 == UWORD(1)) /* special case, adding 1*x to f */ { fmpz_add_ui(f, f, x); return; } if (!COEFF_IS_MPZ(c1)) /* c1 is small */ { mp_limb_t prod[2]; ulong uc1 = FLINT_ABS(c1); umul_ppmm(prod[1], prod[0], uc1, x); /* compute product */ if (prod[1] == 0) /* product fits in one limb */ { if (c1 < WORD(0)) fmpz_sub_ui(f, f, prod[0]); else fmpz_add_ui(f, f, prod[0]); return; } else if ((prod[1] == 1) && (!COEFF_IS_MPZ(r)) && ((r ^ c1) < WORD(0))) { /* only chance at cancellation is if product is one bit past a limb and res is small and opposite sign to this product */ ulong ur = FLINT_ABS(r); if (ur > prod[0]) /* cancellation will occur */ { fmpz_set_ui(f, prod[0] - ur); if (r > WORD(0)) fmpz_neg(f, f); return; } } /* in all remaining cases res is either big already, or will be big in the end */ { __mpz_struct * mpz_ptr = _fmpz_promote_val(f); mpz_t temp; /* set up a temporary, cheap mpz_t to contain prod */ temp->_mp_d = prod; temp->_mp_size = (c1 < WORD(0) ? -2 : 2); mpz_add(mpz_ptr, mpz_ptr, temp); _fmpz_demote_val(f); /* cancellation may have occurred */ } } else /* c1 is large */ { __mpz_struct * mpz_ptr = _fmpz_promote_val(f); flint_mpz_addmul_ui(mpz_ptr, COEFF_TO_PTR(c1), x); _fmpz_demote_val(f); /* cancellation may have occurred */ } }