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
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 #4
0
void fmpz_primorial(fmpz_t res, long n)
{
    mp_size_t len, pi;
    ulong bits;
    __mpz_struct * mpz_ptr;

    if (n <= LARGEST_ULONG_PRIMORIAL)
    {
        if (n <= 2)
            fmpz_set_ui(res, 1 + (n==2));
        else
            fmpz_set_ui(res, ULONG_PRIMORIALS[(n-1)/2-1]);
        return;
    }

    pi = n_prime_pi(n);
    
    n_compute_primes(pi);
    bits = FLINT_BIT_COUNT(flint_primes[pi - 1]);
    
    mpz_ptr = _fmpz_promote(res);
    mpz_realloc2(mpz_ptr, pi*bits);
    
    len = mpn_prod_limbs(mpz_ptr->_mp_d, flint_primes, pi, bits);
    mpz_ptr->_mp_size = len;
}
Exemple #5
0
void fmpz_fib_ui(fmpz_t f, ulong n)
{
    if (n < NUM_SMALL_FIB)
        fmpz_set_ui(f, small_fib[n]);
    else
        mpz_fib_ui(_fmpz_promote(f), n);
}
Exemple #6
0
void fmpz_fac_ui(fmpz_t f, ulong n)
{
    if (n < FLINT_NUM_TINY_FACTORIALS)
        fmpz_set_ui(f, flint_tiny_factorials[n]);
    else
        mpz_fac_ui(_fmpz_promote(f), n);
}
Exemple #7
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 #8
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 #9
0
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);
    }
}
Exemple #10
0
void
fmpz_neg_1arg( fmpz_t v )
// inspired by FLINT fmpz_neg
 {
  if (!COEFF_IS_MPZ(*v))
   *v = -*v;
  else
   {
    __mpz_struct* mpz_ptr = _fmpz_promote(v);
    // TODO: write effective subroutine to invert GMP mpz in-place
    mpz_neg(mpz_ptr, mpz_ptr);
   }
 }
Exemple #11
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 #12
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 #13
0
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));
    }
}
Exemple #14
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 #15
0
void
fmpz_set_mpf(fmpz_t f, const mpf_t x)
{
#if defined(__MPIR_VERSION)
    if (mpf_fits_si_p(x))
#else
    if (flint_mpf_fits_slong_p(x))
#endif
    {
        slong cx = flint_mpf_get_si(x);
        fmpz_set_si(f, cx);
    }
    else
    {
        __mpz_struct *z = _fmpz_promote(f);
        mpz_set_f(z, x);
    }
}
Exemple #16
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 #17
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 #18
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 #19
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 #21
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 */
    }
}