pqc/external/flint-2.4.3/fmpz_poly.h

1176 lines
41 KiB
C

/*=============================================================================
This file is part of FLINT.
FLINT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLINT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLINT; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 William Hart
Copyright (C) 2009, 2011 Andy Novocin
Copyright (C) 2010 Sebastian Pancratz
Copyright (C) 2011 Fredrik Johansson
******************************************************************************/
#ifndef FMPZ_POLY_H
#define FMPZ_POLY_H
#undef ulong
#define ulong ulongxx /* interferes with system includes */
#include <stdio.h>
#undef ulong
#include <gmp.h>
#define ulong mp_limb_t
#include "flint.h"
#include "fmpz.h"
#include "fmpz_vec.h"
#include "nmod_poly.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FMPZ_POLY_INV_NEWTON_CUTOFF 32
/* Type definitions *********************************************************/
typedef struct
{
fmpz * coeffs;
slong alloc;
slong length;
} fmpz_poly_struct;
typedef fmpz_poly_struct fmpz_poly_t[1];
typedef struct
{
fmpz ** powers;
slong len;
} fmpz_poly_powers_precomp_struct;
typedef fmpz_poly_powers_precomp_struct fmpz_poly_powers_precomp_t[1];
typedef struct {
fmpz c;
fmpz_poly_struct *p;
slong *exp;
slong num;
slong alloc;
} fmpz_poly_factor_struct;
typedef fmpz_poly_factor_struct fmpz_poly_factor_t[1];
/* Memory management ********************************************************/
void fmpz_poly_init(fmpz_poly_t poly);
void fmpz_poly_init2(fmpz_poly_t poly, slong alloc);
void fmpz_poly_realloc(fmpz_poly_t poly, slong alloc);
void fmpz_poly_fit_length(fmpz_poly_t poly, slong len);
void fmpz_poly_clear(fmpz_poly_t poly);
void _fmpz_poly_normalise(fmpz_poly_t poly);
static __inline__
void _fmpz_poly_set_length(fmpz_poly_t poly, slong newlen)
{
if (poly->length > newlen)
{
slong i;
for (i = newlen; i < poly->length; i++)
_fmpz_demote(poly->coeffs + i);
}
poly->length = newlen;
}
/* Polynomial parameters ***************************************************/
static __inline__
slong fmpz_poly_length(const fmpz_poly_t poly)
{
return poly->length;
}
static __inline__
slong fmpz_poly_degree(const fmpz_poly_t poly)
{
return poly->length - 1;
}
/* Assignment and basic manipulation ***************************************/
void fmpz_poly_set(fmpz_poly_t poly1, const fmpz_poly_t poly2);
void fmpz_poly_set_ui(fmpz_poly_t poly, ulong c);
void fmpz_poly_set_si(fmpz_poly_t poly, slong c);
void fmpz_poly_set_fmpz(fmpz_poly_t poly, const fmpz_t c);
void fmpz_poly_set_mpz(fmpz_poly_t poly, const mpz_t c);
int _fmpz_poly_set_str(fmpz * poly, const char * str);
int fmpz_poly_set_str(fmpz_poly_t poly, const char * str);
char * _fmpz_poly_get_str(const fmpz * poly, slong len);
char * fmpz_poly_get_str(const fmpz_poly_t poly);
char * _fmpz_poly_get_str_pretty(const fmpz * poly, slong len, const char * x);
char * fmpz_poly_get_str_pretty(const fmpz_poly_t poly, const char * x);
static __inline__
void fmpz_poly_zero(fmpz_poly_t poly)
{
_fmpz_poly_set_length(poly, 0);
}
static __inline__
void fmpz_poly_one(fmpz_poly_t poly)
{
fmpz_poly_set_ui(poly, UWORD(1));
}
void fmpz_poly_zero_coeffs(fmpz_poly_t poly, slong i, slong j);
void fmpz_poly_swap(fmpz_poly_t poly1, fmpz_poly_t poly2);
void _fmpz_poly_reverse(fmpz * res, const fmpz * poly, slong len, slong n);
void fmpz_poly_reverse(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
static __inline__
void fmpz_poly_truncate(fmpz_poly_t poly, slong newlen)
{
if (poly->length > newlen)
{
slong i;
for (i = newlen; i < poly->length; i++)
_fmpz_demote(poly->coeffs + i);
poly->length = newlen;
_fmpz_poly_normalise(poly);
}
}
/* Randomisation ***********************************************************/
void fmpz_poly_randtest(fmpz_poly_t f, flint_rand_t state,
slong len, mp_bitcnt_t bits);
void fmpz_poly_randtest_unsigned(fmpz_poly_t f, flint_rand_t state,
slong len, mp_bitcnt_t bits);
void fmpz_poly_randtest_not_zero(fmpz_poly_t f, flint_rand_t state,
slong len, mp_bitcnt_t bits);
/* Getting and setting coefficients ****************************************/
slong fmpz_poly_get_coeff_si(const fmpz_poly_t poly, slong n);
void fmpz_poly_set_coeff_si(fmpz_poly_t poly, slong n, slong x);
ulong fmpz_poly_get_coeff_ui(const fmpz_poly_t poly, slong n);
void fmpz_poly_set_coeff_ui(fmpz_poly_t poly, slong n, ulong x);
void fmpz_poly_set_coeff_fmpz(fmpz_poly_t poly, slong n, const fmpz_t x);
void fmpz_poly_get_coeff_fmpz(fmpz_t x, const fmpz_poly_t poly, slong n);
#define fmpz_poly_get_coeff_ptr(poly, n) \
((n) < (poly)->length ? (poly)->coeffs + (n) : NULL)
#define fmpz_poly_lead(poly) \
((poly)->length ? (poly)->coeffs + (poly)->length - 1 : NULL)
/* Comparison **************************************************************/
int fmpz_poly_equal(const fmpz_poly_t poly1, const fmpz_poly_t poly2);
#define fmpz_poly_is_zero(poly) \
((poly)->length == 0)
static __inline__
int _fmpz_poly_is_one(const fmpz *poly, slong len)
{
return (len > 0 && fmpz_is_one(poly)
&& _fmpz_vec_is_zero(poly + 1, len - 1));
}
static __inline__
int fmpz_poly_is_one(const fmpz_poly_t op)
{
return (op->length) == 1 && (*(op->coeffs) == WORD(1));
}
static __inline__
int fmpz_poly_is_unit(const fmpz_poly_t op)
{
return (op->length == 1) && (*(op->coeffs) == WORD(1) || *(op->coeffs) == WORD(-1));
}
static __inline__
int fmpz_poly_equal_fmpz(const fmpz_poly_t poly, const fmpz_t c)
{
return ((poly->length == 0) && fmpz_is_zero(c)) ||
((poly->length == 1) && fmpz_equal(poly->coeffs, c));
}
/* Addition and subtraction ************************************************/
void _fmpz_poly_add(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_add(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void _fmpz_poly_sub(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_sub(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void fmpz_poly_neg(fmpz_poly_t res, const fmpz_poly_t poly);
/* Scalar multiplication and division **************************************/
void fmpz_poly_scalar_mul_ui(fmpz_poly_t poly1,
const fmpz_poly_t poly2, ulong x);
void fmpz_poly_scalar_mul_si(fmpz_poly_t poly1,
const fmpz_poly_t poly2, slong x);
void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x);
void fmpz_poly_scalar_addmul_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x);
void fmpz_poly_scalar_submul_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x);
void fmpz_poly_scalar_fdiv_ui(fmpz_poly_t poly1,
const fmpz_poly_t poly2, ulong x);
void fmpz_poly_scalar_fdiv_si(fmpz_poly_t poly1,
const fmpz_poly_t poly2, slong x);
void fmpz_poly_scalar_fdiv_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x);
void fmpz_poly_scalar_tdiv_ui(fmpz_poly_t poly1,
const fmpz_poly_t poly2, ulong x);
void fmpz_poly_scalar_tdiv_si(fmpz_poly_t poly1,
const fmpz_poly_t poly2, slong x);
void fmpz_poly_scalar_tdiv_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x);
void fmpz_poly_scalar_divexact_ui(fmpz_poly_t poly1,
const fmpz_poly_t poly2, ulong x);
void fmpz_poly_scalar_divexact_si(fmpz_poly_t poly1,
const fmpz_poly_t poly2, slong x);
void fmpz_poly_scalar_divexact_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x);
void fmpz_poly_scalar_fdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2,
ulong exp);
void fmpz_poly_scalar_tdiv_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2,
ulong exp);
void fmpz_poly_scalar_mul_2exp(fmpz_poly_t poly1, const fmpz_poly_t poly2,
ulong exp);
static __inline__
void fmpz_poly_scalar_mod_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x)
{
if (poly2->length == 0)
{
fmpz_poly_zero(poly1);
}
else
{
fmpz_poly_fit_length(poly1, poly2->length);
_fmpz_vec_scalar_mod_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x);
_fmpz_poly_set_length(poly1, poly2->length);
_fmpz_poly_normalise(poly1);
}
}
static __inline__
void fmpz_poly_scalar_smod_fmpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const fmpz_t x)
{
if (poly2->length == 0)
{
fmpz_poly_zero(poly1);
}
else
{
fmpz_poly_fit_length(poly1, poly2->length);
_fmpz_vec_scalar_smod_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x);
_fmpz_poly_set_length(poly1, poly2->length);
_fmpz_poly_normalise(poly1);
}
}
/* Bit packing *************************************************************/
void _fmpz_poly_bit_pack(mp_ptr arr, const fmpz * poly,
slong len, mp_bitcnt_t bit_size, int negate);
int _fmpz_poly_bit_unpack(fmpz * poly, slong len,
mp_srcptr arr, mp_bitcnt_t bit_size, int negate);
void _fmpz_poly_bit_unpack_unsigned(fmpz * poly, slong len,
mp_srcptr arr, mp_bitcnt_t bit_size);
void fmpz_poly_bit_pack(fmpz_t f, const fmpz_poly_t poly,
mp_bitcnt_t bit_size);
void fmpz_poly_bit_unpack(fmpz_poly_t poly, const fmpz_t f,
mp_bitcnt_t bit_size);
void fmpz_poly_bit_unpack_unsigned(fmpz_poly_t poly, const fmpz_t f,
mp_bitcnt_t bit_size);
/* Multiplication **********************************************************/
void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_mul_classical(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2, slong n);
void fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2, slong n);
void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1,
slong len1, const fmpz * poly2, slong len2, slong start);
void fmpz_poly_mulhigh_classical(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong start);
void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1,
slong len1, const fmpz * poly2, slong len2);
void fmpz_poly_mulmid_classical(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void fmpz_poly_mul_karatsuba(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_mul_karatsuba(fmpz * res, const fmpz * poly1,
slong len1, const fmpz * poly2, slong len2);
void _fmpz_poly_mullow_karatsuba_n(fmpz * res, const fmpz * poly1,
const fmpz * poly2, slong n);
void fmpz_poly_mullow_karatsuba_n(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
void _fmpz_poly_mulhigh_karatsuba_n(fmpz * res, const fmpz * poly1,
const fmpz * poly2, slong len);
void fmpz_poly_mulhigh_karatsuba_n(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong length);
void _fmpz_poly_mul_KS(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_mul_KS(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_mullow_KS(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2, slong n);
void fmpz_poly_mullow_KS(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2, slong n);
void _fmpz_poly_mul_SS(fmpz * output, const fmpz * input1, slong length1,
const fmpz * input2, slong length2);
void fmpz_poly_mul_SS(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_mullow_SS(fmpz * output, const fmpz * input1, slong length1,
const fmpz * input2, slong length2, slong n);
void fmpz_poly_mullow_SS(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
void _fmpz_poly_mul(fmpz * res, const fmpz * poly1,
slong len1, const fmpz * poly2, slong len2);
void fmpz_poly_mul(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_mullow(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2, slong n);
void fmpz_poly_mullow(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
void fmpz_poly_mulhigh_n(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
/* Squaring ******************************************************************/
void _fmpz_poly_sqr_KS(fmpz * rop, const fmpz * op, slong len);
void fmpz_poly_sqr_KS(fmpz_poly_t rop, const fmpz_poly_t op);
void fmpz_poly_sqr_karatsuba(fmpz_poly_t rop, const fmpz_poly_t op);
void _fmpz_poly_sqr_karatsuba(fmpz * rop, const fmpz * op, slong len);
void _fmpz_poly_sqr_classical(fmpz * rop, const fmpz * op, slong len);
void fmpz_poly_sqr_classical(fmpz_poly_t rop, const fmpz_poly_t op);
void _fmpz_poly_sqr(fmpz * rop, const fmpz * op, slong len);
void fmpz_poly_sqr(fmpz_poly_t rop, const fmpz_poly_t op);
void _fmpz_poly_sqrlow_KS(fmpz * res, const fmpz * poly, slong len, slong n);
void fmpz_poly_sqrlow_KS(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
void _fmpz_poly_sqrlow_karatsuba_n(fmpz * res, const fmpz * poly, slong n);
void fmpz_poly_sqrlow_karatsuba_n(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
void _fmpz_poly_sqrlow_classical(fmpz * res, const fmpz * poly, slong len, slong n);
void fmpz_poly_sqrlow_classical(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, slong len, slong n);
void fmpz_poly_sqrlow(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
/* Powering ****************************************************************/
void _fmpz_poly_pow_multinomial(fmpz * res, const fmpz * poly, slong len, ulong e);
void fmpz_poly_pow_multinomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e);
void _fmpz_poly_pow_binomial(fmpz * res, const fmpz * poly, ulong e);
void fmpz_poly_pow_binomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e);
void _fmpz_poly_pow_binexp(fmpz * res, const fmpz * poly, slong len, ulong e);
void fmpz_poly_pow_binexp(fmpz_poly_t res, const fmpz_poly_t poly, ulong e);
void _fmpz_poly_pow_addchains(fmpz * res, const fmpz * poly, slong len, const int * a, int n);
void fmpz_poly_pow_addchains(fmpz_poly_t res, const fmpz_poly_t poly, ulong e);
void _fmpz_poly_pow_small(fmpz * res, const fmpz * poly, slong len, ulong e);
void _fmpz_poly_pow(fmpz * res, const fmpz * poly, slong len, ulong e);
void fmpz_poly_pow(fmpz_poly_t res, const fmpz_poly_t poly, ulong e);
void _fmpz_poly_pow_trunc(fmpz * res, const fmpz * poly, ulong e, slong n);
void
fmpz_poly_pow_trunc(fmpz_poly_t res, const fmpz_poly_t poly, ulong e, slong n);
/* Shifting ****************************************************************/
void _fmpz_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n);
void _fmpz_poly_shift_right(fmpz * res, const fmpz * poly, slong len, slong n);
void fmpz_poly_shift_left(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
void fmpz_poly_shift_right(fmpz_poly_t res, const fmpz_poly_t poly, slong n);
/* Norms *******************************************************************/
void _fmpz_poly_2norm(fmpz_t res, const fmpz * poly, slong len);
void fmpz_poly_2norm(fmpz_t res, const fmpz_poly_t poly);
mp_bitcnt_t _fmpz_poly_2norm_normalised_bits(const fmpz * poly, slong len);
static __inline__
ulong fmpz_poly_max_limbs(const fmpz_poly_t poly)
{
return _fmpz_vec_max_limbs(poly->coeffs, poly->length);
}
static __inline__
slong fmpz_poly_max_bits(const fmpz_poly_t poly)
{
return _fmpz_vec_max_bits(poly->coeffs, poly->length);
}
static __inline__ void
fmpz_poly_height(fmpz_t res, const fmpz_poly_t poly)
{
_fmpz_vec_height(res, poly->coeffs, poly->length);
}
/* Greatest common divisor *************************************************/
void _fmpz_poly_gcd_subresultant(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_gcd_subresultant(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
int fmpz_poly_gcd_heuristic(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_gcd_modular(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_gcd_modular(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
void _fmpz_poly_gcd(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_gcd(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void _fmpz_poly_lcm(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_lcm(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void _fmpz_poly_resultant(fmpz_t res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_resultant(fmpz_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void _fmpz_poly_xgcd_modular(fmpz_t r, fmpz * s, fmpz * t,
const fmpz * poly1, slong len1, const fmpz * poly2, slong len2);
void fmpz_poly_xgcd_modular(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t,
const fmpz_poly_t poly1, const fmpz_poly_t poly2);
static __inline__
void _fmpz_poly_xgcd(fmpz_t r, fmpz * s, fmpz * t,
const fmpz * poly1, slong len1, const fmpz * poly2, slong len2)
{
_fmpz_poly_xgcd_modular(r, s, t, poly1, len1, poly2, len2);
}
static __inline__
void fmpz_poly_xgcd(fmpz_t r, fmpz_poly_t s, fmpz_poly_t t,
const fmpz_poly_t poly1, const fmpz_poly_t poly2)
{
fmpz_poly_xgcd_modular(r, s, t, poly1, poly2);
}
/* Gaussian content ********************************************************/
void _fmpz_poly_content(fmpz_t res, const fmpz * poly, slong len);
void fmpz_poly_content(fmpz_t res, const fmpz_poly_t poly);
void _fmpz_poly_primitive_part(fmpz * res, const fmpz * poly, slong len);
void fmpz_poly_primitive_part(fmpz_poly_t res, const fmpz_poly_t poly);
/* Square-free *************************************************************/
int _fmpz_poly_is_squarefree(const fmpz * poly, slong len);
int fmpz_poly_is_squarefree(const fmpz_poly_t poly);
/* Euclidean division ******************************************************/
void _fmpz_poly_divrem_basecase(fmpz * Q, fmpz * R, const fmpz * A,
slong lenA, const fmpz * B, slong lenB);
void fmpz_poly_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R,
const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_divrem_divconquer_recursive(fmpz * Q, fmpz * BQ, fmpz * W,
const fmpz * A, const fmpz * B, slong lenB);
void _fmpz_poly_divrem_divconquer(fmpz * Q, fmpz * R,
const fmpz * A, slong lenA, const fmpz * B, slong lenB);
void fmpz_poly_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R,
const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_divrem(fmpz * Q, fmpz * R, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_divrem(fmpz_poly_t Q, fmpz_poly_t R, const fmpz_poly_t A,
const fmpz_poly_t B);
void _fmpz_poly_div_basecase(fmpz * Q, fmpz * R, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_div_basecase(fmpz_poly_t Q,
const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_divremlow_divconquer_recursive(fmpz * Q, fmpz * QB,
const fmpz * A, const fmpz * B, slong lenB);
void _fmpz_poly_div_divconquer_recursive(fmpz * Q, fmpz * temp,
const fmpz * A, const fmpz * B, slong lenB);
void _fmpz_poly_div_divconquer(fmpz * Q, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_div_divconquer(fmpz_poly_t Q,
const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_div(fmpz * Q, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_div(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_preinvert(fmpz * B_inv, const fmpz * B, slong n);
void fmpz_poly_preinvert(fmpz_poly_t B_inv, const fmpz_poly_t B);
void _fmpz_poly_div_preinv(fmpz * Q, const fmpz * A, slong len1,
const fmpz * B, const fmpz * B_inv, slong len2);
void fmpz_poly_div_preinv(fmpz_poly_t Q, const fmpz_poly_t A,
const fmpz_poly_t B, const fmpz_poly_t B_inv);
void _fmpz_poly_divrem_preinv(fmpz * Q, fmpz * A, slong len1,
const fmpz * B, const fmpz * B_inv, slong len2);
void fmpz_poly_divrem_preinv(fmpz_poly_t Q, fmpz_poly_t R,
const fmpz_poly_t A, const fmpz_poly_t B, const fmpz_poly_t B_inv);
fmpz ** _fmpz_poly_powers_precompute(const fmpz * B, slong len);
void fmpz_poly_powers_precompute(fmpz_poly_powers_precomp_t pinv,
fmpz_poly_t poly);
void _fmpz_poly_powers_clear(fmpz ** powers, slong len);
void fmpz_poly_powers_clear(fmpz_poly_powers_precomp_t pinv);
void _fmpz_poly_rem_powers_precomp(fmpz * A, slong m,
const fmpz * B, slong n, fmpz ** const powers);
void fmpz_poly_rem_powers_precomp(fmpz_poly_t R,
const fmpz_poly_t A, const fmpz_poly_t B,
const fmpz_poly_powers_precomp_t B_inv);
void _fmpz_poly_rem_basecase(fmpz * Q, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_rem_basecase(fmpz_poly_t R,
const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_rem(fmpz * R, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_rem(fmpz_poly_t R, const fmpz_poly_t A, const fmpz_poly_t B);
void
fmpz_poly_div_root(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_t c);
void
_fmpz_poly_div_root(fmpz * Q, const fmpz * A, slong len, const fmpz_t c);
/* Power series division ***************************************************/
void _fmpz_poly_inv_series_newton(fmpz * Qinv, const fmpz * Q, slong n);
void fmpz_poly_inv_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n);
static __inline__ void
_fmpz_poly_inv_series(fmpz * Qinv, const fmpz * Q, slong n)
{
_fmpz_poly_inv_series_newton(Qinv, Q, n);
}
static __inline__ void
fmpz_poly_inv_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n)
{
fmpz_poly_inv_series_newton(Qinv, Q, n);
}
void _fmpz_poly_div_series(fmpz * Q, const fmpz * A, const fmpz * B, slong n);
void fmpz_poly_div_series(fmpz_poly_t Q, const fmpz_poly_t A,
const fmpz_poly_t B, slong n);
/* Divisibility testing ***************************************************/
int _fmpz_poly_divides(fmpz * q, const fmpz * a,
slong len1, const fmpz * b, slong len2);
int fmpz_poly_divides(fmpz_poly_t q, const fmpz_poly_t a, const fmpz_poly_t b);
/* Pseudo division *********************************************************/
void _fmpz_poly_pseudo_divrem_basecase(fmpz * Q, fmpz * R,
ulong * d, const fmpz * A, slong A_len,
const fmpz * B, slong B_len, const fmpz_preinvn_t inv);
void fmpz_poly_pseudo_divrem_basecase(fmpz_poly_t Q, fmpz_poly_t R,
ulong * d, const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_pseudo_divrem_divconquer(fmpz * Q, fmpz * R,
ulong * d, const fmpz * A, slong lenA,
const fmpz * B, slong lenB, const fmpz_preinvn_t inv);
void fmpz_poly_pseudo_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R,
ulong * d, const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A,
slong lenA, const fmpz * B, slong lenB);
void fmpz_poly_pseudo_divrem_cohen(fmpz_poly_t Q, fmpz_poly_t R,
const fmpz_poly_t A, const fmpz_poly_t B);
void _fmpz_poly_pseudo_rem_cohen(fmpz * R, const fmpz * A, slong lenA,
const fmpz * B, slong lenB);
void fmpz_poly_pseudo_rem_cohen(fmpz_poly_t R, const fmpz_poly_t A,
const fmpz_poly_t B);
static __inline__
void _fmpz_poly_pseudo_divrem(fmpz * Q, fmpz * R,
ulong * d, const fmpz * A, slong A_len,
const fmpz * B, slong B_len, const fmpz_preinvn_t inv)
{
_fmpz_poly_pseudo_divrem_divconquer(Q, R, d, A, A_len, B, B_len, inv);
}
static __inline__
void fmpz_poly_pseudo_divrem(fmpz_poly_t Q, fmpz_poly_t R,
ulong * d, const fmpz_poly_t A, const fmpz_poly_t B)
{
fmpz_poly_pseudo_divrem_divconquer(Q, R, d, A, B);
}
void _fmpz_poly_pseudo_div(fmpz * Q, ulong * d, const fmpz * A, slong lenA,
const fmpz * B, slong lenB, const fmpz_preinvn_t inv);
void fmpz_poly_pseudo_div(fmpz_poly_t Q, ulong * d, const fmpz_poly_t A,
const fmpz_poly_t B);
void _fmpz_poly_pseudo_rem(fmpz * R, ulong * d, const fmpz * A, slong lenA,
const fmpz * B, slong lenB, const fmpz_preinvn_t inv);
void fmpz_poly_pseudo_rem(fmpz_poly_t R, ulong * d, const fmpz_poly_t A,
const fmpz_poly_t B);
/* Derivative **************************************************************/
void _fmpz_poly_derivative(fmpz * rpoly, const fmpz * poly, slong len);
void fmpz_poly_derivative(fmpz_poly_t res, const fmpz_poly_t poly);
/* Evaluation **************************************************************/
void
_fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz * poly, slong len,
const fmpz_t a);
void fmpz_poly_evaluate_divconquer_fmpz(fmpz_t res, const fmpz_poly_t poly,
const fmpz_t a);
void _fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz * f, slong len,
const fmpz_t a);
void fmpz_poly_evaluate_horner_fmpz(fmpz_t res, const fmpz_poly_t f,
const fmpz_t a);
void _fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz * f, slong len, const fmpz_t a);
void fmpz_poly_evaluate_fmpz(fmpz_t res, const fmpz_poly_t f, const fmpz_t a);
void _fmpz_poly_evaluate_horner_mpq(fmpz_t rnum, fmpz_t rden,
const fmpz * f, slong len,
const fmpz_t anum, const fmpz_t aden);
void fmpz_poly_evaluate_horner_mpq(mpq_t res, const fmpz_poly_t f,
const mpq_t a);
void _fmpz_poly_evaluate_mpq(fmpz_t rnum, fmpz_t rden,
const fmpz * f, slong len,
const fmpz_t anum, const fmpz_t aden);
void fmpz_poly_evaluate_mpq(mpq_t res, const fmpz_poly_t f, const mpq_t a);
mp_limb_t _fmpz_poly_evaluate_mod(const fmpz * poly, slong len, mp_limb_t a,
mp_limb_t n, mp_limb_t ninv);
mp_limb_t fmpz_poly_evaluate_mod(const fmpz_poly_t poly, mp_limb_t a,
mp_limb_t n);
void
_fmpz_poly_evaluate_divconquer(fmpz * res, const fmpz * poly, slong len,
const fmpz_t x);
void
fmpz_poly_evaluate_divconquer(fmpz_t res,
const fmpz_poly_t poly, const fmpz_t x);
/* Composition *************************************************************/
void _fmpz_poly_compose_horner(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_compose_horner(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_compose_divconquer(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
void _fmpz_poly_compose(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2);
void fmpz_poly_compose(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_poly_t poly2);
/* Taylor shift ************************************************************/
void _fmpz_poly_taylor_shift_horner(fmpz * poly, const fmpz_t c, slong n);
void fmpz_poly_taylor_shift_horner(fmpz_poly_t g, const fmpz_poly_t f,
const fmpz_t c);
void _fmpz_poly_taylor_shift_divconquer(fmpz * poly, const fmpz_t c, slong n);
void fmpz_poly_taylor_shift_divconquer(fmpz_poly_t g, const fmpz_poly_t f,
const fmpz_t c);
void _fmpz_poly_taylor_shift(fmpz * poly, const fmpz_t c, slong n);
void fmpz_poly_taylor_shift(fmpz_poly_t g, const fmpz_poly_t f, const fmpz_t c);
/* Power series composition and compositional inverse **********************/
void
_fmpz_poly_compose_series_brent_kung(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2, slong n);
void
fmpz_poly_compose_series_brent_kung(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
void
_fmpz_poly_compose_series_horner(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2, slong n);
void
fmpz_poly_compose_series_horner(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
void
_fmpz_poly_compose_series(fmpz * res, const fmpz * poly1, slong len1,
const fmpz * poly2, slong len2, slong n);
void
fmpz_poly_compose_series(fmpz_poly_t res,
const fmpz_poly_t poly1, const fmpz_poly_t poly2, slong n);
void
_fmpz_poly_revert_series_lagrange(fmpz * Qinv, const fmpz * Q, slong n);
void
fmpz_poly_revert_series_lagrange(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n);
void
_fmpz_poly_revert_series_lagrange_fast(fmpz * Qinv, const fmpz * Q, slong n);
void
fmpz_poly_revert_series_lagrange_fast(fmpz_poly_t Qinv,
const fmpz_poly_t Q, slong n);
void
_fmpz_poly_revert_series_newton(fmpz * Qinv, const fmpz * Q, slong n);
void
fmpz_poly_revert_series_newton(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n);
void
_fmpz_poly_revert_series(fmpz * Qinv, const fmpz * Q, slong n);
void
fmpz_poly_revert_series(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n);
/* Square root *************************************************************/
int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, slong len);
int fmpz_poly_sqrt_classical(fmpz_poly_t b, const fmpz_poly_t a);
int _fmpz_poly_sqrt(fmpz * res, const fmpz * poly, slong len);
int fmpz_poly_sqrt(fmpz_poly_t b, const fmpz_poly_t a);
/* Signature ***************************************************************/
void _fmpz_poly_signature(slong * r1, slong * r2, const fmpz * poly, slong len);
void fmpz_poly_signature(slong * r1, slong * r2, const fmpz_poly_t poly);
/* Input and output ********************************************************/
int fmpz_poly_fprint(FILE * file, const fmpz_poly_t poly);
int _fmpz_poly_fprint_pretty(FILE * file,
const fmpz * poly, slong len, const char * x);
int fmpz_poly_fprint_pretty(FILE * file,
const fmpz_poly_t poly, const char * x);
static __inline__
int fmpz_poly_print(const fmpz_poly_t poly)
{
return fmpz_poly_fprint(stdout, poly);
}
static __inline__
int fmpz_poly_print_pretty(const fmpz_poly_t poly, const char * x)
{
return fmpz_poly_fprint_pretty(stdout, poly, x);
}
int fmpz_poly_fread(FILE * file, fmpz_poly_t poly);
int fmpz_poly_fread_pretty(FILE *file, fmpz_poly_t poly, char **x);
static __inline__
int fmpz_poly_read(fmpz_poly_t poly)
{
return fmpz_poly_fread(stdin, poly);
}
static __inline__
int fmpz_poly_read_pretty(fmpz_poly_t poly, char **x)
{
return fmpz_poly_fread_pretty(stdin, poly, x);
}
static __inline__
void fmpz_poly_debug(const fmpz_poly_t poly)
{
flint_printf("(alloc = %wd, length = %wd, vec = ", poly->alloc, poly->length);
if (poly->coeffs)
{
flint_printf("{");
_fmpz_vec_print(poly->coeffs, poly->alloc);
flint_printf("}");
}
else
{
flint_printf("NULL");
}
flint_printf(")");
fflush(stdout);
}
/* CRT ********************************************************************/
void fmpz_poly_get_nmod_poly(nmod_poly_t res, const fmpz_poly_t poly);
void fmpz_poly_set_nmod_poly(fmpz_poly_t res, const nmod_poly_t poly);
void fmpz_poly_set_nmod_poly_unsigned(fmpz_poly_t res, const nmod_poly_t poly);
void
_fmpz_poly_CRT_ui_precomp(fmpz * res, const fmpz * poly1, slong len1,
const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2,
mp_limb_t m2inv, fmpz_t m1m2, mp_limb_t c, int sign);
void _fmpz_poly_CRT_ui(fmpz * res, const fmpz * poly1, slong len1,
const fmpz_t m1, mp_srcptr poly2, slong len2, mp_limb_t m2,
mp_limb_t m2inv, int sign);
void fmpz_poly_CRT_ui(fmpz_poly_t res, const fmpz_poly_t poly1,
const fmpz_t m1, const nmod_poly_t poly2,
int sign);
/* Products *****************************************************************/
void _fmpz_poly_product_roots_fmpz_vec(fmpz * poly,
const fmpz * xs, slong n);
void fmpz_poly_product_roots_fmpz_vec(fmpz_poly_t poly,
const fmpz * xs, slong n);
/* Newton basis *************************************************************/
void _fmpz_poly_monomial_to_newton(fmpz * poly, const fmpz * roots, slong n);
void _fmpz_poly_newton_to_monomial(fmpz * poly, const fmpz * roots, slong n);
/* Multipoint evaluation and interpolation *********************************/
void
fmpz_poly_evaluate_fmpz_vec(fmpz * res, const fmpz_poly_t f,
const fmpz * a, slong n);
void
fmpz_poly_interpolate_fmpz_vec(fmpz_poly_t poly,
const fmpz * xs, const fmpz * ys, slong n);
/* Hensel lifting ************************************************************/
void fmpz_poly_hensel_build_tree(slong * link, fmpz_poly_t *v, fmpz_poly_t *w,
const nmod_poly_factor_t fac);
void fmpz_poly_hensel_lift(fmpz_poly_t Gout, fmpz_poly_t Hout,
fmpz_poly_t Aout, fmpz_poly_t Bout,
const fmpz_poly_t f,
const fmpz_poly_t g, const fmpz_poly_t h,
const fmpz_poly_t a, const fmpz_poly_t b,
const fmpz_t p, const fmpz_t p1);
void _fmpz_poly_hensel_lift_without_inverse(fmpz *G, fmpz *H,
const fmpz *f, slong lenF,
const fmpz *g, slong lenG, const fmpz *h, slong lenH,
const fmpz *a, slong lenA, const fmpz *b, slong lenB,
const fmpz_t p, const fmpz_t p1);
void fmpz_poly_hensel_lift_without_inverse(fmpz_poly_t Gout, fmpz_poly_t Hout,
const fmpz_poly_t f, const fmpz_poly_t g, const fmpz_poly_t h,
const fmpz_poly_t a, const fmpz_poly_t b,
const fmpz_t p, const fmpz_t p1);
void _fmpz_poly_hensel_lift_only_inverse(fmpz *A, fmpz *B,
const fmpz *G, slong lenG, const fmpz *H, slong lenH,
const fmpz *a, slong lenA, const fmpz *b, slong lenB,
const fmpz_t p, const fmpz_t p1);
void fmpz_poly_hensel_lift_only_inverse(fmpz_poly_t Aout, fmpz_poly_t Bout,
const fmpz_poly_t G, const fmpz_poly_t H,
const fmpz_poly_t a, const fmpz_poly_t b,
const fmpz_t p, const fmpz_t p1);
void fmpz_poly_hensel_lift_tree_recursive(slong *link,
fmpz_poly_t *v, fmpz_poly_t *w, fmpz_poly_t f, slong j, slong inv,
const fmpz_t p0, const fmpz_t p1);
void fmpz_poly_hensel_lift_tree(slong *link, fmpz_poly_t *v, fmpz_poly_t *w,
fmpz_poly_t f, slong r, const fmpz_t p, slong e0, slong e1, slong inv);
slong _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, slong *link,
fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f,
const nmod_poly_factor_t local_fac, slong target_exp);
slong _fmpz_poly_hensel_continue_lift(fmpz_poly_factor_t lifted_fac,
slong *link, fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f,
slong prev, slong curr, slong N, const fmpz_t p);
void fmpz_poly_hensel_lift_once(fmpz_poly_factor_t lifted_fac,
const fmpz_poly_t f,
const nmod_poly_factor_t local_fac, slong N);
/* Some functions for backwards compatibility */
static __inline__ void fmpz_poly_scalar_mul_mpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const mpz_t x)
{
fmpz_t t;
fmpz_init_set_readonly(t, x);
fmpz_poly_scalar_mul_fmpz(poly1, poly2, t);
fmpz_clear_readonly(t);
}
static __inline__ void fmpz_poly_scalar_divexact_mpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const mpz_t x)
{
fmpz_t t;
fmpz_init_set_readonly(t, x);
fmpz_poly_scalar_divexact_fmpz(poly1, poly2, t);
fmpz_clear_readonly(t);
}
static __inline__ void fmpz_poly_scalar_fdiv_mpz(fmpz_poly_t poly1,
const fmpz_poly_t poly2, const mpz_t x)
{
fmpz_t t;
fmpz_init_set_readonly(t, x);
fmpz_poly_scalar_fdiv_fmpz(poly1, poly2, t);
fmpz_clear_readonly(t);
}
static __inline__ void fmpz_poly_set_coeff_mpz(fmpz_poly_t poly, slong n,
const mpz_t x)
{
fmpz_t t;
fmpz_init_set_readonly(t, x);
fmpz_poly_set_coeff_fmpz(poly, n, t);
fmpz_clear_readonly(t);
}
static __inline__ void fmpz_poly_get_coeff_mpz(mpz_t x, const fmpz_poly_t poly, slong n)
{
fmpz_t t;
fmpz_init(t);
fmpz_poly_get_coeff_fmpz(t, poly, n);
fmpz_get_mpz(x, t);
fmpz_clear(t);
}
/* Roots */
void _fmpz_poly_bound_roots(fmpz_t bound, const fmpz * poly, slong len);
void fmpz_poly_bound_roots(fmpz_t bound, const fmpz_poly_t poly);
#ifdef __cplusplus
}
#endif
#include "fmpz_poly_factor.h"
#endif