Esempio n. 1
0
File: neg.c Progetto: goens/flint2
void fmpq_poly_neg(fmpq_poly_t poly1, const fmpq_poly_t poly2)
{
    if (poly1 == poly2)
    {
        _fmpz_vec_neg(poly1->coeffs, poly2->coeffs, poly2->length);
    }
    else
    {
        fmpq_poly_fit_length(poly1, poly2->length);
        _fmpz_vec_neg(poly1->coeffs, poly2->coeffs, poly2->length);
        _fmpq_poly_set_length(poly1, poly2->length);
        fmpz_set(poly1->den, poly2->den);
    }
}
Esempio n. 2
0
void _fmpq_poly_canonicalise(fmpz * poly, fmpz_t den, slong len)
{
    if (*den == WORD(1))
        return;
    
    if (*den == WORD(-1))
    {
        _fmpz_vec_neg(poly, poly, len);
        fmpz_one(den);
    }
    else if (len == 0)
    {
        fmpz_one(den);
    }
    else
    {
        fmpz_t gcd;
        fmpz_init(gcd);
        _fmpz_vec_content(gcd, poly, len);
        if (*gcd != WORD(1))
            fmpz_gcd(gcd, gcd, den);
        if (fmpz_sgn(den) < 0)
            fmpz_neg(gcd, gcd);
        if (*gcd != WORD(1))
        {
            _fmpz_vec_scalar_divexact_fmpz(poly, poly, len, gcd);
            fmpz_divexact(den, den, gcd);
        }
        fmpz_clear(gcd);
    }
}
Esempio n. 3
0
File: div.c Progetto: goens/flint2
void _fmpq_poly_div(fmpz * Q, fmpz_t q, 
                    const fmpz * A, const fmpz_t a, long lenA, 
                    const fmpz * B, const fmpz_t b, long lenB)
{
    long lenQ = lenA - lenB + 1;
    ulong d;
    const fmpz * lead = B + (lenB - 1);
    
    if (lenB == 1)
    {
        _fmpq_poly_scalar_div_fmpq(Q, q, A, a, lenA, B, b);
        return;
    }
    
    /* 
       From pseudo division over Z we have 
           lead^d * A = Q * B + R
       and thus
           {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}.
     */
    _fmpz_poly_pseudo_div(Q, &d, A, lenA, B, lenB);
    
    /* 1.  lead^d == +-1.  {Q, q} = {b Q, a} up to sign */
    if (d == 0UL || *lead == 1L || *lead == -1L)
    {
        fmpz_one(q);
        _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b);
        _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, a);
        
        if (*lead == -1L && d % 2UL)
            _fmpz_vec_neg(Q, Q, lenQ);
    }
    /* 2.  lead^d != +-1.  {Q, q} = {b Q, a lead^d} */
    else
    {
        /*
           TODO:  Improve this.  Clearly we do not need to compute 
           den = a lead^d in many cases, but can determine the GCD from 
           lead alone already.
         */
        fmpz_t den;
        fmpz_init(den);
        fmpz_pow_ui(den, lead, d);
        fmpz_mul(den, a, den);
        
        fmpz_one(q);
        _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b);
        _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, den);
        
        fmpz_clear(den);
    }
}
Esempio n. 4
0
/* 
   Returns 1 if sign * (G, glen) * (Q, qlen) = (P, len), else returns 0.
   Temp requires space for glen + qlen - 1 coefficients
*/
int multiplies_out(fmpz * P, long len, const fmpz * Q, long qlen, 
                   const fmpz * G, long glen, long sign, fmpz * temp)
{
   int divides = 0;

   /* multiply out */
   if (qlen >= glen)
      _fmpz_poly_mul(temp, Q, qlen, G, glen);
   else
      _fmpz_poly_mul(temp, G, glen, Q, qlen);
   if (sign < 0L) _fmpz_vec_neg(temp, temp, glen + qlen - 1);

   /* check if quotient really was exact */
   divides = (glen + qlen - 1 == len && _fmpz_vec_equal(temp, P, len));

   return divides;
}
Esempio n. 5
0
void _fmpq_poly_scalar_div_si(fmpz * rpoly, fmpz_t rden, const fmpz * poly,
                              const fmpz_t den, long len, long c)
{
    if (c == 1)
    {
        if (rpoly != poly)
        {
            _fmpz_vec_set(rpoly, poly, len);
            fmpz_set(rden, den);
        }
    }
    else if (c == -1)
    {
        _fmpz_vec_neg(rpoly, poly, len);
        fmpz_set(rden, den);
    }
    else
    {
        fmpz_t d, f;

        fmpz_init(d);
        fmpz_init(f);
        
        fmpz_set_si(f, c);
        _fmpz_vec_content(d, poly, len);
        fmpz_gcd(d, d, f);

        if (c > 0)
        {
            _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, d);
            fmpz_mul_si(rden, den, c / fmpz_get_si(d));
        }
        else
        {
            ulong q = (- (ulong) c) / fmpz_get_ui(d);

            fmpz_neg(d, d);
            _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, d);
            fmpz_mul_ui(rden, den, q);
        }

        fmpz_clear(d);
        fmpz_clear(f);
    }
}
Esempio n. 6
0
void 
_fmpq_poly_invsqrt_series(fmpz * rpoly, fmpz_t rden, 
                      const fmpz * poly, const fmpz_t den, long n)
{
    long m;
    fmpz * t, * u;
    fmpz_t tden, uden;

    if (n == 1)
    {
        fmpz_one(rpoly);
        fmpz_one(rden);
        return;
    }

    m = (n + 1) / 2;

    _fmpq_poly_invsqrt_series(rpoly, rden, poly, den, m);

    fmpz_init(tden);
    fmpz_init(uden);
    t = _fmpz_vec_init(n);
    u = _fmpz_vec_init(n);

    _fmpz_vec_zero(rpoly + m, n - m);

    _fmpq_poly_mul(t, tden, rpoly, rden, m, rpoly, rden, m);
    if (2*m - 1 < n)
        fmpz_zero(t + n - 1);

    _fmpq_poly_mullow(u, uden, t, tden, n, rpoly, rden, n, n);
    _fmpq_poly_mullow(t, tden, u, uden, n, poly, den, n, n);
    _fmpz_vec_neg(t + m, t + m, n - m);
    _fmpz_vec_zero(t, m);
    fmpz_mul_ui(tden, tden, 2UL);
    _fmpq_poly_canonicalise(t, tden, n);

    _fmpq_poly_add(rpoly, rden, rpoly, rden, m, t, tden, n);

    fmpz_clear(tden);
    fmpz_clear(uden);
    _fmpz_vec_clear(t, n);
    _fmpz_vec_clear(u, n);
}
Esempio n. 7
0
void 
_fmpq_poly_inv_series_newton(fmpz * Qinv, fmpz_t Qinvden, 
                             const fmpz * Q, const fmpz_t Qden, long n)
{
    if (n == 1)
    {
        if (fmpz_sgn(Q) > 0)
        {
            fmpz_set(Qinv, Qden);
            fmpz_set(Qinvden, Q);
        }
        else
        {
            fmpz_neg(Qinv, Qden);
            fmpz_neg(Qinvden, Q);
        }
    }
    else
    {
        const long alloc = FLINT_MAX(n, 3 * FMPQ_POLY_INV_NEWTON_CUTOFF);
        long *a, i, m;
        fmpz *W, *Wden;

        W = _fmpz_vec_init(alloc + 1);
        Wden = W + alloc;

        for (i = 1; (1L << i) < n; i++) ;

        a = (long *) flint_malloc(i * sizeof(long));
        a[i = 0] = n;
        while (n >= FMPQ_POLY_INV_NEWTON_CUTOFF)
            a[++i] = (n = (n + 1) / 2);

        /* Base case */
        {
            fmpz *rev = W + 2 * FMPQ_POLY_INV_NEWTON_CUTOFF;

            _fmpz_poly_reverse(rev, Q, n, n);
            _fmpz_vec_zero(W, 2*n - 2);
            fmpz_one(W + (2*n - 2));
            fmpz_one(Wden);

            _fmpq_poly_div(Qinv, Qinvden, W, Wden, 2*n - 1, rev, Qden, n);
            _fmpq_poly_canonicalise(Qinv, Qinvden, n);

            _fmpz_poly_reverse(Qinv, Qinv, n, n);
        }

        for (i--; i >= 0; i--)
        {
            m = n;
            n = a[i];

            _fmpz_poly_mullow(W, Q, n, Qinv, m, n);
            fmpz_mul(Wden, Qden, Qinvden);

            _fmpz_poly_mullow(Qinv + m, Qinv, m, W + m, n - m, n - m);
            fmpz_mul(Qinvden, Qinvden, Wden);
            _fmpz_vec_scalar_mul_fmpz(Qinv, Qinv, m, Wden);

            _fmpz_vec_neg(Qinv + m, Qinv + m, n - m);

            _fmpq_poly_canonicalise(Qinv, Qinvden, n);
        }

        _fmpz_vec_clear(W, alloc + 1);
        flint_free(a);
    }
}
Esempio n. 8
0
void _fmpq_poly_divrem(fmpz * Q, fmpz_t q, fmpz * R, fmpz_t r, 
                       const fmpz * A, const fmpz_t a, slong lenA, 
          const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv)
{
    slong lenQ = lenA - lenB + 1;
    slong lenR = lenB - 1;
    ulong d;
    const fmpz * lead = B + (lenB - 1);
    
    if (lenB == 1)
    {
        _fmpq_poly_scalar_div_fmpq(Q, q, A, a, lenA, B, b);
        fmpz_one(r);
        return;
    }
    
    /* 
       From pseudo division over Z we have 
           lead^d * A = Q * B + R
       and thus
           {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}.
     */
    _fmpz_poly_pseudo_divrem(Q, R, &d, A, lenA, B, lenB, inv);
    
    /* Determine the actual length of R */
    for ( ; lenR != 0 && fmpz_is_zero(R + (lenR - 1)); lenR--) ;
    
    /* 1.  lead^d == +-1.  {Q, q} = {b Q, a}, {R, r} = {R, a} up to sign */
    if (d == UWORD(0) || *lead == WORD(1) || *lead == WORD(-1))
    {
        fmpz_one(q);
        _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b);
        _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, a);
        
        fmpz_one(r);
        if (lenR > 0)
            _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, a);
        
        if (*lead == WORD(-1) && d % UWORD(2))
        {
            _fmpz_vec_neg(Q, Q, lenQ);
            _fmpz_vec_neg(R, R, lenR);
        }
    }
    /* 2.  lead^d != +-1.  {Q, q} = {b Q, a lead^d}, {R, r} = {R, a lead^d} */
    else
    {
        /*
           TODO:  Improve this.  Clearly we do not need to compute 
           den = a lead^d in many cases, but can determine the GCD from 
           lead alone already.
         */
        fmpz_t den;
        fmpz_init(den);
        fmpz_pow_ui(den, lead, d);
        fmpz_mul(den, a, den);
        
        fmpz_one(q);
        _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b);
        _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, den);
        
        fmpz_one(r);
        if (lenR > 0)
            _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, den);
        
        fmpz_clear(den);
    }
}
Esempio n. 9
0
void _fmpq_poly_scalar_div_mpq(fmpz * rpoly, fmpz_t rden, 
                               const fmpz * poly, const fmpz_t den, long len, 
                               const fmpz_t r, const fmpz_t s)
{
    fmpz_t gcd1;  /* GCD( poly, r ) */
    fmpz_t gcd2;  /* GCD( s, den )  */
    fmpz_init(gcd1);
    fmpz_init(gcd2);
    fmpz_set_ui(gcd1, 1);
    fmpz_set_ui(gcd2, 1);
    if (*r != 1L)
    {
        _fmpz_vec_content(gcd1, poly, len);
        if (*gcd1 != 1L)
            fmpz_gcd(gcd1, gcd1, r);
    }
    if (*den != 1L && *s != 1L)
        fmpz_gcd(gcd2, s, den);
    
    if (*gcd1 == 1L)
    {
        if (*gcd2 == 1L)
        {
            _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, s);
            fmpz_mul(rden, den, r);
        }
        else
        {
            fmpz_t s2;
            fmpz_init(s2);
            fmpz_divexact(s2, s, gcd2);
            _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, s2);
            fmpz_divexact(rden, den, gcd2);
            fmpz_mul(rden, rden, r);
            fmpz_clear(s2);
        }
    }
    else
    {
        fmpz_t r2;
        fmpz_init(r2);
        fmpz_divexact(r2, r, gcd1);
        if (*gcd2 == 1L)
        {
            _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1);
            _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, s);
            fmpz_mul(rden, den, r2);
        }
        else
        {
            fmpz_t s2;
            fmpz_init(s2);
            fmpz_divexact(s2, s, gcd2);
            _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1);
            _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, s2);
            fmpz_divexact(rden, den, gcd2);
            fmpz_mul(rden, rden, r2);
            fmpz_clear(s2);
        }
        fmpz_clear(r2);
    }
    
    if (_fmpz_vec_is_zero(rpoly, len))
        fmpz_set_ui(rden, 1);
    if (fmpz_sgn(rden) < 0)
    {
        _fmpz_vec_neg(rpoly, rpoly, len);
        fmpz_neg(rden, rden);
    }
    
    fmpz_clear(gcd1);
    fmpz_clear(gcd2);
}
Esempio n. 10
0
/* Assumes len1 != 0 != len2 */
int
_fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, long len1, 
                                        const fmpz * poly2, long len2)
{
	ulong bits1, bits2, max_bits, pack_bits, bound_bits, bits_G, bits_Q;
   ulong limbs1, limbs2, limbsg, pack_limbs, qlimbs;
   ulong log_glen, log_length;
   long sign1, sign2, glen, qlen;
	fmpz_t ac, bc, d, gc;
   fmpz * A, * B, * G, * Q, * t;
   mp_ptr array1, array2, arrayg, q, temp;
   int divides;

   fmpz_init(ac);
   fmpz_init(bc);
   fmpz_init(d);
   
	/* compute gcd of content of poly1 and poly2 */
   _fmpz_poly_content(ac, poly1, len1);
   _fmpz_poly_content(bc, poly2, len2);
   fmpz_gcd(d, ac, bc);

   /* special case, one of the polys is a constant */
   if (len2 == 1) /* if len1 == 1 then so does len2 */
   {
      fmpz_set(res, d);

      fmpz_clear(ac);
      fmpz_clear(bc);
	   fmpz_clear(d);

      return 1;
   }
   
   /* divide poly1 and poly2 by their content */
   A = _fmpz_vec_init(len1);
   B = _fmpz_vec_init(len2);
   _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, ac);
   _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, bc);
   fmpz_clear(ac);
   fmpz_clear(bc);
	   
	/* special case, one of the polys is length 2 */
   if (len2 == 2) /* if len1 == 2 then so does len2 */
	{
		Q = _fmpz_vec_init(len1 - len2 + 1);
		if (_fmpz_poly_divides(Q, A, len1, B, 2))
      {
		   _fmpz_vec_scalar_mul_fmpz(res, B, 2, d);
         if (fmpz_sgn(res + 1) < 0)
            _fmpz_vec_neg(res, res, 2);
      }
		else  
      {
			fmpz_set(res, d);
         fmpz_zero(res + 1);
      }

		fmpz_clear(d);
		_fmpz_vec_clear(A, len1);
      _fmpz_vec_clear(B, len2);
      _fmpz_vec_clear(Q, len1 - len2 + 1);
      
      return 1;
	}
	
   /* 
      Determine how many bits (pack_bits) to pack into. The bound 
      bound_bits ensures that if G | A and G | B with G primitive 
      then G is the gcd of A and B. The bound is taken from 
      http://arxiv.org/abs/cs/0206032v1
   */
   bits1 = FLINT_ABS(_fmpz_vec_max_bits(A, len1));
	bits2 = FLINT_ABS(_fmpz_vec_max_bits(B, len2));
	max_bits = FLINT_MAX(bits1, bits2);
   			
	bound_bits = FLINT_MIN(bits1, bits2) + 6; 
	pack_bits = FLINT_MAX(bound_bits, max_bits); /* need to pack original polys */
   pack_limbs = (pack_bits - 1)/FLINT_BITS + 1;
   
	if (pack_bits >= 32) /* pack into multiples of limbs if >= 32 bits */
      pack_bits = FLINT_BITS*pack_limbs;
		
   /* allocate space to pack into */
   limbs1 = (pack_bits*len1 - 1)/FLINT_BITS + 1;
   limbs2 = (pack_bits*len2 - 1)/FLINT_BITS + 1;
	array1 = flint_calloc(limbs1, sizeof(mp_limb_t));
   array2 = flint_calloc(limbs2, sizeof(mp_limb_t));
   arrayg = flint_calloc(limbs2, sizeof(mp_limb_t));
   
   /* pack first poly and normalise */
   sign1 = (long) fmpz_sgn(A + len1 - 1);
	_fmpz_poly_bit_pack(array1, A, len1, pack_bits, sign1);
	while (array1[limbs1 - 1] == 0) limbs1--;

   /* pack second poly and normalise */
   sign2 = (long) fmpz_sgn(B + len2 - 1);
   _fmpz_poly_bit_pack(array2, B, len2, pack_bits, sign2);
	while (array2[limbs2 - 1] == 0) limbs2--;
	
	/* compute integer GCD */
   limbsg = mpn_gcd_full(arrayg, array1, limbs1, array2, limbs2);
	
   /* 
      Make space for unpacked gcd. May have one extra coeff due to 
      1 0 -x being packed as 0 -1 -x. 
   */
   glen = FLINT_MIN((limbsg*FLINT_BITS)/pack_bits + 1, len2); 
   G = _fmpz_vec_init(glen);
   
   /* unpack gcd */
   _fmpz_poly_bit_unpack(G, glen, arrayg, pack_bits, 0);
   while (G[glen - 1] == 0) glen--;
   
	/* divide by any content */
   fmpz_init(gc);
	_fmpz_poly_content(gc, G, glen);

   if (!fmpz_is_one(gc)) 
      limbsg = mpn_tdiv_q_fmpz_inplace(arrayg, limbsg, gc);

   /* make space for quotient and remainder of first poly by gcd */
   qlimbs = limbs1 - limbsg + 1;
   qlen = FLINT_MIN(len1, (qlimbs*FLINT_BITS)/pack_bits + 1);
   qlimbs = (qlen*pack_bits - 1)/FLINT_BITS + 1;
   q = flint_calloc(qlimbs, sizeof(mp_limb_t));
   temp = flint_malloc(limbsg*sizeof(mp_limb_t));
   
	divides = 0;

   if (mpn_divides(q, array1, limbs1, arrayg, limbsg, temp)) 
	{
      /* unpack quotient of first poly by gcd */
      Q = _fmpz_vec_init(len1); 
      t = _fmpz_vec_init(len1 + glen);
      _fmpz_poly_bit_unpack(Q, qlen, q, pack_bits, 0);
      while (Q[qlen - 1] == 0) qlen--;
      
      /* divide by content */
      _fmpz_vec_scalar_divexact_fmpz(G, G, glen, gc);
		
      /* check if we really need to multiply out to check for exact quotient */
      bits_G = FLINT_ABS(_fmpz_vec_max_bits(G, glen));
		bits_Q = FLINT_ABS(_fmpz_vec_max_bits(Q, qlen));
		log_glen = FLINT_BIT_COUNT(glen);
		log_length = FLINT_MIN(log_glen, FLINT_BIT_COUNT(qlen));
       
	   divides = (bits_G + bits_Q + log_length < pack_bits);
     
      if (!divides) /* need to multiply out to check exact quotient */
         divides = multiplies_out(A, len1, Q, qlen, G, glen, sign1, t);

		if (divides) /* quotient really was exact */
		{
         mpn_zero(q, qlimbs);
          
         if (mpn_divides(q, array2, limbs2, arrayg, limbsg, temp)) 
	      {
            /* unpack quotient of second poly by gcd */
            qlimbs = limbs2 - limbsg + 1;
            qlen = FLINT_MIN(len2, (qlimbs*FLINT_BITS - 1)/pack_bits + 1);
            _fmpz_poly_bit_unpack(Q, qlen, q, pack_bits, 0);
            while (Q[qlen - 1] == 0) qlen--;
            
            /* check if we really need to multiply out to check for exact quotient */
            bits_Q = FLINT_ABS(_fmpz_vec_max_bits(Q, qlen));
				log_length = FLINT_MIN(log_glen, FLINT_BIT_COUNT(qlen));

				divides = (bits_G + bits_Q + log_length < pack_bits);
		      
            if (!divides) /* we need to multiply out */
               divides = multiplies_out(B, len2, Q, qlen, G, glen, sign1, t);
			} 
		} 

      _fmpz_vec_clear(t, len1 + glen);
      _fmpz_vec_clear(Q, len1);
	}

   flint_free(q); 
	flint_free(temp); 
	flint_free(arrayg); 
	flint_free(array1); 
	flint_free(array2); 
	fmpz_clear(gc); 
	
	_fmpz_vec_clear(A, len1);
	_fmpz_vec_clear(B, len2);
	
   /* we found the gcd, so multiply by content */
   if (divides)
   {
	   _fmpz_vec_zero(res + glen, len2 - glen);
      _fmpz_vec_scalar_mul_fmpz(res, G, glen, d);
   }
		
   fmpz_clear(d);
   _fmpz_vec_clear(G, glen);
		
   return divides;
}
Esempio n. 11
0
void _padic_poly_sub(fmpz *rop, slong *val, slong N, 
                     const fmpz *op1, slong val1, slong len1, slong N1, 
                     const fmpz *op2, slong val2, slong len2, slong N2, 
                     const padic_ctx_t ctx)
{
    const slong len = FLINT_MAX(len1, len2);

    *val = FLINT_MIN(val1, val2);

    if (val1 == val2)
    {
        _fmpz_poly_sub(rop, op1, len1, op2, len2);
        _padic_poly_canonicalise(rop, val, len, ctx->p);
    }
    else
    {
        fmpz_t x;

        fmpz_init(x);
        if (val1 < val2)  /* F := p^g (G - p^{h-g} H) */
        {
            fmpz_pow_ui(x, ctx->p, val2 - val1);

            if (rop == op1)
            {
                _fmpz_vec_zero(rop + len1, len2 - len1);
                _fmpz_vec_scalar_submul_fmpz(rop, op2, len2, x);
            }
            else
            {
                _fmpz_vec_scalar_mul_fmpz(rop, op2, len2, x);
                _fmpz_vec_neg(rop, rop, len2);
                _fmpz_poly_add(rop, op1, len1, rop, len2);
            }
        }
        else  /* F := p^h (p^(g-h) G - H) */
        {
            fmpz_pow_ui(x, ctx->p, val1 - val2);

            if (rop == op2)
            {
                _fmpz_vec_neg(rop, op2, len2);
                _fmpz_vec_zero(rop + len2, len1 - len2);
                _fmpz_vec_scalar_addmul_fmpz(rop, op1, len1, x);
            }
            else
            {
                _fmpz_vec_scalar_mul_fmpz(rop, op1, len1, x);
                _fmpz_poly_sub(rop, rop, len1, op2, len2);
            }
        }
        fmpz_clear(x);
    }

    /* Reduce */
    if (N - *val > 0)
    {
        fmpz_t pow;
        int alloc;

        alloc = _padic_ctx_pow_ui(pow, N - *val, ctx);

        if (N >= N1 && N >= N2)
        {
            slong i;
            for (i = 0; i < len; i++)
                if (fmpz_sgn(rop + i) < 0)
                    fmpz_add(rop + i, rop + i, pow);
        }
        else
        {
            _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pow);
        }

        if (alloc)
            fmpz_clear(pow);
    }
    else
    {
        _fmpz_vec_zero(rop, len);
        *val = 0;
    }
}
Esempio n. 12
0
void _fmpz_poly_signature(long * r1, long * r2, fmpz * poly, long len)
{
    fmpz *A, *B, *f, *g, *h, *w;
    long lenA, lenB;
    int s, t;

    if (len <= 2)
    {
        *r1 = (len == 2);
        *r2 = 0;
        return;
    }

    w = _fmpz_vec_init(2 * len + 2);
    A = w;
    B = w + len;
    lenA = len;
    lenB = lenA - 1;
    f = w + 2 * len - 1;
    g = w + 2 * len;
    h = w + 2 * len + 1;

    _fmpz_poly_primitive_part(A, poly, lenA);
    _fmpz_poly_derivative(B, A, lenA);
    _fmpz_poly_primitive_part(B, B, lenB);

    fmpz_one(g);
    fmpz_one(h);

    s = 1;
    t = (lenA & 1L) ? -s : s;
    *r1 = 1;

    while (1)
    {
        long delta = lenA - lenB;
        int sgnA;

        _fmpz_poly_pseudo_rem_cohen(A, A, lenA, B, lenB);

        lenA = lenB;
        FMPZ_VEC_NORM(A, lenA);

        if (lenA == 0)
        {
            printf("Exception: non-squarefree polynomial detected in fmpz_poly_signature\n");
            _fmpz_vec_clear(w, 2 * len + 2);
            abort();
        }

        if ((fmpz_sgn(B + (lenB - 1)) > 0) || (delta & 1L))
            _fmpz_vec_neg(A, A, lenA);

        sgnA = fmpz_sgn(A + (lenA - 1));
        if (sgnA != s)
        {
            s = -s;
            (*r1)--;
        }
        if (sgnA != ((lenA & 1L) ? t : -t))
        {
            t = -t;
            (*r1)++;
        }

        if (lenA == 1)
        {
            *r2 = ((len - 1) - *r1) / 2;

            _fmpz_vec_clear(w, 2 * len + 2);
            return;
        }
        else
        {
            {
                fmpz * temp = A;
                A = B;
                B = temp;
            }
            {
                long temp = lenA;
                lenA = lenB;
                lenB = temp;
            }

            if (delta == 1)
            {
                fmpz_mul(f, g, h);
                _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, f);
                fmpz_set(g, A + (lenA - 1));
                fmpz_set(h, g);
            }
            else
            {
                fmpz_pow_ui(f, h, delta);
                fmpz_mul(f, f, g);
                _fmpz_vec_scalar_divexact_fmpz(B, B, lenB, f);
                fmpz_pow_ui(f, h, delta - 1);
                fmpz_pow_ui(g, A + (lenA - 1), delta);
                fmpz_divexact(h, g, f);
                fmpz_set(g, A + (lenA - 1));
            }
        }
    }
}