Exemple #1
0
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 */
    }
}
Exemple #2
0
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);
            }
        }
    }
}
Exemple #3
0
int
main(void)
{
    int i, result;
    flint_rand_t state;

    printf("fmpz....");
    fflush(stdout);

    for (i = 0; i < 100000; i++)
    {
        fmpz_t a, b;

        *a = 0L;

        fmpz_randtest(a, state, FLINT_BITS - 2);

        *b = *a;

        _fmpz_promote_val(a);
        _fmpz_demote_val(a);

        result = (*b == *a);

        if (!result)
        {
            printf("FAIL\n");
            abort();
        }
    }

    _fmpz_cleanup();
    printf("PASS\n");
    return 0;
}
Exemple #4
0
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 */
    }
}
Exemple #5
0
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 */
    }
}
Exemple #6
0
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 */
        }
    }
}
Exemple #7
0
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 */
        }
    }
}
Exemple #8
0
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 */
    }
}
Exemple #9
0
void
number_of_partitions(fmpz_t x, ulong n)
{
    if (n < NUMBER_OF_SMALL_PARTITIONS)
    {
        fmpz_set_ui(x, partitions_lookup[n]);
    }
    else
    {
        mpfr_t t;
        mpfr_init(t);
        number_of_partitions_mpfr(t, n);
        mpfr_get_z(_fmpz_promote(x), t, MPFR_RNDN);
        _fmpz_demote_val(x);
        mpfr_clear(t);
    }
}
Exemple #10
0
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 */
        }
    }
}
Exemple #11
0
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);
    }
}
Exemple #12
0
void
fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly,
                   mp_bitcnt_t bit_size)
{
    long len;
    __mpz_struct * mpz;
    long i, d;
    int negate;

    len = fmpz_poly_length(poly);

    if (len == 0 || bit_size == 0)
    {
        fmpz_zero(f);
        return;
    }

    mpz = _fmpz_promote(f);
    mpz_realloc2(mpz, len * bit_size);
    d = mpz->_mp_alloc;

    mpn_zero(mpz->_mp_d, d);

    if (fmpz_sgn(fmpz_poly_lead(poly)) < 0)
        negate = -1;
    else
        negate = 0;

    _fmpz_poly_bit_pack(mpz->_mp_d, poly->coeffs, len, bit_size, negate);

    for (i = d - 1; i >= 0; i--)
    {
        if (mpz->_mp_d[i] != 0)
            break;
    }
    d = i + 1;

    mpz->_mp_size = d;
    _fmpz_demote_val(f);

    if (negate)
        fmpz_neg(f, f);
}
Exemple #13
0
void
arf_get_fmpz(fmpz_t z, const arf_t x, arf_rnd_t rnd)
{
    if (arf_is_special(x))
    {
        if (arf_is_zero(x))
        {
            fmpz_zero(z);
        }
        else
        {
            flint_printf("arf_get_fmpz: cannot convert infinity or nan to integer\n");
            abort();
        }
    }
    else if (COEFF_IS_MPZ(*ARF_EXPREF(x)))
    {
        /* tiny */
        if (fmpz_sgn(ARF_EXPREF(x)) < 0)
        {
            int negative = ARF_SGNBIT(x);

            if (rnd == ARF_RND_NEAR
                    || rnd == ARF_RND_DOWN
                    || (rnd == ARF_RND_FLOOR && !negative)
                    || (rnd == ARF_RND_CEIL && negative))
            {
                fmpz_zero(z);
            }
            else
            {
                fmpz_set_si(z, negative ? -1 : 1);
            }
        }
        else
        {
            flint_printf("arf_get_fmpz: number too large to convert to integer\n");
            abort();
        }
    }
    else
    {
        slong exp;
        int negative, inexact;
        mp_size_t xn, zn;
        mp_srcptr xp;
        __mpz_struct * zz;

        /* TBD: implement efficiently */
        if (rnd == ARF_RND_NEAR)
        {
            fmpr_t t;
            fmpr_init(t);
            arf_get_fmpr(t, x);
            fmpr_get_fmpz(z, t, rnd);
            fmpr_clear(t);
            return;
        }

        exp = ARF_EXP(x);
        negative = ARF_SGNBIT(x);

        /* |x| < 1 */
        if (exp <= 0)
        {
            if (rnd == ARF_RND_DOWN ||
                    (rnd == ARF_RND_FLOOR && !negative) ||
                    (rnd == ARF_RND_CEIL && negative))
            {
                fmpz_zero(z);
            }
            else
            {
                fmpz_set_si(z, negative ? -1 : 1);
            }
            return;
        }

        ARF_GET_MPN_READONLY(xp, xn, x);

        /* |x| < 2^31 or 2^63 (must save 1 bit for rounding up!) */
        if (exp < FLINT_BITS)
        {
            mp_limb_t v, v2;

            v = xp[xn - 1];
            v2 = v >> (FLINT_BITS - exp);
            inexact = (xn > 1) || ((v2 << (FLINT_BITS - exp)) != v);

            if (inexact && rnd != ARF_RND_DOWN)
            {
                if (negative && (rnd == ARF_RND_UP || rnd == ARF_RND_FLOOR))
                    v2++;
                if (!negative && (rnd == ARF_RND_UP || rnd == ARF_RND_CEIL))
                    v2++;
            }

            if (negative)
                fmpz_neg_ui(z, v2);
            else
                fmpz_set_ui(z, v2);

            return;
        }

        /* |x| >= 1 */
        zn = (exp + FLINT_BITS - 1) / FLINT_BITS;
        zz = _fmpz_promote(z);

        if (zz->_mp_alloc < zn)
            mpz_realloc2(zz, zn * FLINT_BITS);

        inexact = _arf_get_integer_mpn(zz->_mp_d, xp, xn, exp);

        zz->_mp_size = negative ? -zn : zn;
        _fmpz_demote_val(z);

        if (inexact && rnd != ARF_RND_DOWN)
        {
            if (negative && (rnd == ARF_RND_UP || rnd == ARF_RND_FLOOR))
                fmpz_sub_ui(z, z, 1);

            if (!negative && (rnd == ARF_RND_UP || rnd == ARF_RND_CEIL))
                fmpz_add_ui(z, z, 1);
        }
    }
Exemple #14
0
void fmpz_powm_ui(fmpz_t f, const fmpz_t g, ulong e, const fmpz_t m)
{
    if (fmpz_sgn(m) <= 0)
    {
        printf("Exception (fmpz_powm_ui).  Modulus is less than 1.\n");
        abort();
    }

    if (fmpz_is_one(m))
    {
        fmpz_zero(f);
    }
    else if (e == 0)
    {
        fmpz_one(f);
    }
    else  /* e != 0, m > 0 */
    {
        fmpz g2 = *g;
        fmpz m2 = *m;

        if (!COEFF_IS_MPZ(m2))  /* m is small */
        {
            if (!COEFF_IS_MPZ(g2))  /* g is small */
            {
                mp_limb_t minv = n_preinvert_limb(m2);

                _fmpz_demote(f);

                if (g2 >= 0)
                {
                    g2 = n_mod2_preinv(g2, m2, minv);
                    *f = n_powmod2_preinv(g2, e, m2, minv);
                }
                else
                {
                    g2 = n_mod2_preinv(-g2, m2, minv);
                    *f = n_powmod2_preinv(g2, e, m2, minv);
                    if ((e & 1UL))
                        *f = n_negmod(*f, m2);
                }
            }
            else  /* g is large */
            {
                __mpz_struct *ptr = _fmpz_promote(f);
                mpz_t m3;

                mpz_init_set_ui(m3, m2);
                mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, m3);
                mpz_clear(m3);

                _fmpz_demote_val(f);
            }
        }
        else  /* m is large */
        {
            if (!COEFF_IS_MPZ(g2))  /* g is small */
            {
                __mpz_struct *ptr = _fmpz_promote(f);
                mpz_t g3;

                mpz_init_set_si(g3, g2);
                mpz_powm_ui(ptr, g3, e, COEFF_TO_PTR(m2));
                mpz_clear(g3);

                _fmpz_demote_val(f);
            }
            else  /* g is large */
            {
               __mpz_struct *ptr = _fmpz_promote(f);

                mpz_powm_ui(ptr, COEFF_TO_PTR(g2), e, COEFF_TO_PTR(m2));

                _fmpz_demote_val(f);
            }
        }
    }
}
void
_arith_cos_minpoly(fmpz * coeffs, slong d, ulong n)
{
    slong i, j;
    fmpz * alpha;
    fmpz_t half;
    mpfr_t t, u;
    mp_bitcnt_t prec;
    slong exp;

    if (n <= MAX_32BIT)
    {
        for (i = 0; i <= d; i++)
            fmpz_set_si(coeffs + i, lookup_table[n - 1][i]);
        return;
    }

    /* Direct formula for odd primes > 3 */
    if (n_is_prime(n))
    {
        slong s = (n - 1) / 2;

        switch (s % 4)
        {
            case 0:
                fmpz_set_si(coeffs, WORD(1));
                fmpz_set_si(coeffs + 1, -s);
                break;
            case 1:
                fmpz_set_si(coeffs, WORD(1));
                fmpz_set_si(coeffs + 1, s + 1);
                break;
            case 2:
                fmpz_set_si(coeffs, WORD(-1));
                fmpz_set_si(coeffs + 1, s);
                break;
            case 3:
                fmpz_set_si(coeffs, WORD(-1));
                fmpz_set_si(coeffs + 1, -s - 1);
                break;
        }

        for (i = 2; i <= s; i++)
        {
            slong b = (s - i) % 2;
            fmpz_mul2_uiui(coeffs + i, coeffs + i - 2, s+i-b, s+2-b-i);
            fmpz_divexact2_uiui(coeffs + i, coeffs + i, i, i-1);
            fmpz_neg(coeffs + i, coeffs + i);
        }

        return;
    }

    prec = magnitude_bound(d) + 5 + FLINT_BIT_COUNT(d);

    alpha = _fmpz_vec_init(d);
    fmpz_init(half);
    mpfr_init2(t, prec);
    mpfr_init2(u, prec);

    fmpz_one(half);
    fmpz_mul_2exp(half, half, prec - 1);
    mpfr_const_pi(t, prec);
    mpfr_div_ui(t, t, n, MPFR_RNDN);

    for (i = j = 0; j < d; i++)
    {
        if (n_gcd(n, i) == 1)
        {
            mpfr_mul_ui(u, t, 2 * i, MPFR_RNDN);
            mpfr_cos(u, u, MPFR_RNDN);
            mpfr_neg(u, u, MPFR_RNDN);
            exp = mpfr_get_z_2exp(_fmpz_promote(alpha + j), u);
            _fmpz_demote_val(alpha + j);
            fmpz_mul_or_div_2exp(alpha + j, alpha + j, exp + prec);
            j++;
        }
    }

    balanced_product(coeffs, alpha, d, prec);

    /* Scale and round */
    for (i = 0; i < d + 1; i++)
    {
        slong r = d;
        if ((n & (n - 1)) == 0)
            r--;
        fmpz_mul_2exp(coeffs + i, coeffs + i, r);
        fmpz_add(coeffs + i, coeffs + i, half);
        fmpz_fdiv_q_2exp(coeffs + i, coeffs + i, prec);
    }

    fmpz_clear(half);
    mpfr_clear(t);
    mpfr_clear(u);
    _fmpz_vec_clear(alpha, d);
}
Exemple #16
0
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 */
    }
}
Exemple #17
0
void
fmpz_fdiv_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))
    {
        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 ((c2 > 0L && r < 0L) || (c2 < 0L && r > 0L))
            {
                q--;            /* q cannot overflow as remainder implies |c2| != 1 */
                r += c2;
            }

            fmpz_set_si(f, q);
            fmpz_set_si(s, r);
        }
        else                    /* h is large and g is small */
        {
            if (c1 == 0L)
            {
                fmpz_set_ui(f, 0L); /* g is zero */
                fmpz_set_si(s, c1);
            }
            else if ((c1 < 0L && fmpz_sgn(h) < 0) || (c1 > 0L && fmpz_sgn(h) > 0))  /* signs are the same */
            {
                fmpz_zero(f);   /* quotient is positive, round down to zero */
                fmpz_set_si(s, c1);
            }
            else
            {
                fmpz_add(s, g, h);
                fmpz_set_si(f, -1L);    /* quotient is negative, round down to minus one */
            }
        }
    }
    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 */
            {
                mpz_fdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), c2);
            }
            else
            {
                mpz_cdiv_qr_ui(mpz_ptr, mpz_ptr2, COEFF_TO_PTR(c1), -c2);
                mpz_neg(mpz_ptr, mpz_ptr);
            }
        }
        else                    /* both are large */
        {
            mpz_fdiv_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 */
    }
}