예제 #1
0
파일: get_mpfr.c 프로젝트: clear731/lattice
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);
}
예제 #2
0
파일: tdiv_qr.c 프로젝트: clear731/lattice
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 */
    }
}
예제 #3
0
파일: fdiv_q.c 프로젝트: goens/flint2
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 */
    }
}
예제 #4
0
파일: fits_si.c 프로젝트: clear731/lattice
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
    }
}
예제 #5
0
파일: fprint.c 프로젝트: goens/flint2
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));
}
예제 #6
0
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 */
}
예제 #7
0
파일: tdiv_q_ui.c 프로젝트: goens/flint2
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 */
    }
}
예제 #8
0
파일: fdiv_ui.c 프로젝트: goens/flint2
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);
    }
}
예제 #9
0
파일: get_mpfr.c 프로젝트: argriffing/arb
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();
        }
    }
예제 #10
0
파일: gcd.c 프로젝트: goens/flint2
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 */
        }
    }
}
예제 #11
0
파일: divexact.c 프로젝트: clear731/lattice
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 */
        }
    }
}
예제 #12
0
파일: fits_si.c 프로젝트: goens/flint2
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));
    }
}
예제 #13
0
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);
    }
}
예제 #14
0
파일: fmpz_single.c 프로젝트: goens/flint2
__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);
}
예제 #15
0
파일: cmpabs.c 프로젝트: goens/flint2
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)); 
    }
}
예제 #16
0
파일: dlog.c 프로젝트: clear731/lattice
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;
    }
}
예제 #17
0
파일: size.c 프로젝트: clear731/lattice
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));
}
예제 #18
0
파일: fmpz_single.c 프로젝트: goens/flint2
__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);
}
예제 #19
0
파일: add.c 프로젝트: goens/flint2
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 */
        }
    }
}
예제 #20
0
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;
}
예제 #21
0
파일: cmp_ui.c 프로젝트: goens/flint2
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);
}
예제 #22
0
파일: powm.c 프로젝트: clear731/lattice
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);
            }
        }
    }
}
예제 #23
0
파일: sub_ui.c 프로젝트: goens/flint2
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 */
    }
}
예제 #24
0
파일: set.c 프로젝트: goens/flint2
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));
    }
}
예제 #25
0
파일: clrbit.c 프로젝트: clear731/lattice
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);
    }
}
예제 #26
0
파일: mul_si.c 프로젝트: goens/flint2
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);
    }
}
예제 #27
0
파일: fmpz_single.c 프로젝트: goens/flint2
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 */
}
예제 #28
0
/* 
   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;
   } 
}
예제 #29
0
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;
}
예제 #30
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 */
    }
}