///////////////////////////////////////////////////////////////////////////////1// Copyright (C) 2010 Sebastian Pancratz //2// //3// Distributed under the terms of the GNU General Public License as //4// published by the Free Software Foundation; either version 2 of the //5// License, or (at your option) any later version. //6// //7// http://www.gnu.org/licenses/ //8///////////////////////////////////////////////////////////////////////////////910#ifndef _FMPQ_POLY_H_11#define _FMPQ_POLY_H_1213#ifdef __cplusplus14extern "C" {15#endif1617#include <stdio.h>18#include <gmp.h>1920#include "fmpz.h"21#include "fmpz_poly.h"2223/**24* \file fmpq_poly.h25* \brief Fast implementation of the rational polynomial ring26* \author Sebastian Pancratz27* \date Mar 2010 -- July 201028* \version 0.1.829*/3031/**32* \ingroup Definitions33* \brief Data type for a rational polynomial.34* \details We represent a rational polynomial as the quotient of an integer35* polynomial of type <tt>fmpz_poly_t</tt> and a denominator of type36* <tt>fmpz_t</tt>, enforcing coprimality and that the denominator37* is positive. The zero polynomial is represented as \f$0/1\f$.38*/39typedef struct40{41fmpz_poly_t num; //!< Numerator42fmpz_t den; //!< Denominator43} fmpq_poly_struct;4445/**46* \ingroup Definitions47* \brief Array of #fmpq_poly_struct of length one.48* \details This allows passing <em>by reference</em> without having to49* explicitly allocate memory for the structure, as one would have50* to when using pointers.51*/52typedef fmpq_poly_struct fmpq_poly_t[1];5354/**55* \ingroup Definitions56* \brief Pointer to #fmpq_poly_struct.57*/58typedef fmpq_poly_struct * fmpq_poly_ptr;5960void fmpq_poly_canonicalize(fmpq_poly_ptr f, fmpz_t temp);6162///////////////////////////////////////////////////////////////////////////////63// fmpq_poly_* //64///////////////////////////////////////////////////////////////////////////////6566///////////////////////////////////////////////////////////////////////////////67// Accessing numerator and denominator6869/**70* \def fmpq_poly_numref(op)71* \brief Returns a reference to the numerator of \c op.72* \ingroup NumDen73* \details The <tt>fmpz_poly</tt> functions can be used on the result of74* this macro.75*/76#define fmpq_poly_numref(op) ((op)->num)7778/**79* \def fmpq_poly_denref(op)80* \brief Returns a reference to the denominator of \c op.81* \ingroup NumDen82* \details The <tt>fmpz</tt> functions can be used on the result of83* this macro.84*/85#define fmpq_poly_denref(op) ((op)->den)8687///////////////////////////////////////////////////////////////////////////////88// Memory management8990/**91* \ingroup MemoryManagement92*93* Initializes the element \c rop to zero.94*95* This function should be called once for the #fmpq_poly_ptr \c rop, before96* using it with other <tt>fmpq_poly</tt> functions, or following a97* preceeding call to #fmpq_poly_clear().98*/99static inline100void fmpq_poly_init(fmpq_poly_ptr rop)101{102fmpz_poly_init(rop->num);103rop->den = fmpz_init(1ul);104fmpz_set_ui(rop->den, 1ul);105}106107/**108* \ingroup MemoryManagement109*110* Clears the element \c rop.111*112* This function should only be called on an element which has been113* initialised.114*/115static inline116void fmpq_poly_clear(fmpq_poly_ptr rop)117{118fmpz_poly_clear(rop->num);119fmpz_clear(rop->den);120}121122///////////////////////////////////////////////////////////////////////////////123// Assignment and basic manipulation124125/**126* \ingroup Assignment127*128* Sets the element \c rop to the same value as the element \c op.129*/130static inline131void fmpq_poly_set(fmpq_poly_ptr rop, const fmpq_poly_ptr op)132{133if (rop != op)134{135fmpz_poly_set(rop->num, op->num);136137rop->den = fmpz_realloc(rop->den, fmpz_size(op->den));138fmpz_set(rop->den, op->den);139}140}141142/**143* \ingroup Assignment144*145* Sets the element \c rop to the same value as the element \c op.146*/147static inline148void fmpq_poly_set_fmpz_poly(fmpq_poly_ptr rop, const fmpz_poly_t op)149{150fmpz_poly_set(rop->num, op);151fmpz_set_ui(rop->den, 1);152}153154/**155* \ingroup Assignment156*157* Sets the element \c rop to the value given by the \c int \c op.158*/159static inline160void fmpq_poly_set_si(fmpq_poly_ptr rop, long op)161{162fmpz_poly_zero(rop->num);163fmpz_poly_set_coeff_si(rop->num, 0, op);164fmpz_set_ui(rop->den, 1ul);165}166167/**168* \ingroup Assignment169*170* Sets the element \c rop to the integer \c x.171*/172static inline173void fmpq_poly_set_fmpz(fmpq_poly_ptr rop, const fmpz_t x)174{175fmpz_poly_zero(rop->num);176fmpz_poly_set_coeff_fmpz(rop->num, 0, x);177fmpz_set_ui(rop->den, 1ul);178}179180/**181* \ingroup Assignment182*183* Sets the element \c rop to the integer \c x.184*/185static inline186void fmpq_poly_set_mpz(fmpq_poly_ptr rop, const mpz_t x)187{188fmpz_poly_zero(rop->num);189fmpz_poly_set_coeff_mpz(rop->num, 0, x);190fmpz_set_ui(rop->den, 1ul);191}192193/**194* \ingroup Assignment195*196* Sets the element \c rop to the rational \c x, assumed to be given197* in lowest terms.198*/199static inline200void fmpq_poly_set_mpq(fmpq_poly_ptr rop, const mpq_t x)201{202fmpz_poly_zero(rop->num);203fmpz_poly_set_coeff_mpz(rop->num, 0, mpq_numref(x));204rop->den = fmpz_realloc(rop->den, mpz_size(mpq_denref(x)));205mpz_to_fmpz(rop->den, mpq_denref(x));206}207208/**209* \ingroup Assignment210*211* Swaps the elements \c op1 and \c op2.212*213* This is done efficiently by swapping pointers.214*/215static inline216void fmpq_poly_swap(fmpq_poly_ptr op1, fmpq_poly_ptr op2)217{218if (op1 != op2)219{220fmpz_t t;221fmpz_poly_swap(op1->num, op2->num);222t = op1->den;223op1->den = op2->den;224op2->den = t;225}226}227228/**229* \ingroup Assignment230*231* Sets the element \c rop to zero.232*/233static inline234void fmpq_poly_zero(fmpq_poly_ptr rop)235{236fmpz_poly_zero(rop->num);237fmpz_set_ui(rop->den, 1ul);238}239240/**241* \ingroup Assignment242*243* Sets the element \c rop to one.244*/245static inline246void fmpq_poly_one(fmpq_poly_ptr rop)247{248fmpz_poly_zero(rop->num);249fmpz_poly_set_coeff_si(rop->num, 0, 1);250fmpz_set_ui(rop->den, 1ul);251}252253void fmpq_poly_neg(fmpq_poly_ptr rop, const fmpq_poly_ptr op);254void fmpq_poly_inv(fmpq_poly_ptr rop, const fmpq_poly_ptr op);255256///////////////////////////////////////////////////////////////////////////////257// Setting/ retrieving individual coefficients258259void fmpq_poly_get_coeff_mpq(mpq_t rop, const fmpq_poly_ptr op, ulong i);260261void fmpq_poly_set_coeff_fmpz(fmpq_poly_ptr rop, ulong i, const fmpz_t x);262void fmpq_poly_set_coeff_mpz(fmpq_poly_ptr rop, ulong i, const mpz_t x);263void fmpq_poly_set_coeff_mpq(fmpq_poly_ptr rop, ulong i, const mpq_t x);264void fmpq_poly_set_coeff_si(fmpq_poly_ptr rop, ulong i, long x);265266///////////////////////////////////////////////////////////////////////////////267// Comparison268269/**270* \brief Returns whether \c op is zero.271* \ingroup Comparison272*273* Returns whether the element \c op is zero.274*/275static inline276int fmpq_poly_is_zero(const fmpq_poly_ptr op)277{278return op->num->length == 0ul;279}280281/**282* \brief Returns whether \c op is equal to \f$1\f$.283* \ingroup Comparison284*285* Returns whether the element \c op is equal to the constant polynomial286* \f$1\f$.287*/288static inline289int fmpq_poly_is_one(const fmpq_poly_ptr op)290{291return (op->num->length == 1ul) && fmpz_is_one(op->num->coeffs)292&& fmpz_is_one(op->den);293}294295int fmpq_poly_equal(const fmpq_poly_ptr op1, const fmpq_poly_ptr op2);296int fmpq_poly_cmp(const fmpq_poly_ptr left, const fmpq_poly_ptr right);297298///////////////////////////////////////////////////////////////////////////////299// Polynomial parameters300301/**302* \brief Returns the length of \c op.303* \ingroup PolyParameters304* \details Returns the length of the polynomial \c op, which is one greater305* than its degree.306*/307static inline308ulong fmpq_poly_length(const fmpq_poly_ptr op)309{310return op->num->length;311}312313/**314* \brief Returns the degree of \c op.315* \ingroup Parameters316* \details Returns the degree of the polynomial \c op.317*/318static inline319long fmpq_poly_degree(const fmpq_poly_ptr op)320{321return (long) (op->num->length - 1ul);322}323324///////////////////////////////////////////////////////////////////////////////325// Addition/ subtraction326327void fmpq_poly_add(fmpq_poly_ptr rop, const fmpq_poly_ptr op1, const fmpq_poly_ptr op2);328void fmpq_poly_sub(fmpq_poly_ptr rop, const fmpq_poly_ptr op1, const fmpq_poly_ptr op2);329330void fmpq_poly_addmul(fmpq_poly_ptr rop, const fmpq_poly_ptr op1, const fmpq_poly_ptr op2);331void fmpq_poly_submul(fmpq_poly_ptr rop, const fmpq_poly_ptr op1, const fmpq_poly_ptr op2);332333///////////////////////////////////////////////////////////////////////////////334// Scalar multiplication and division335336void fmpq_poly_scalar_mul_si(fmpq_poly_ptr rop, const fmpq_poly_ptr op, long x);337void fmpq_poly_scalar_mul_mpz(fmpq_poly_ptr rop, const fmpq_poly_ptr op, const mpz_t x);338void fmpq_poly_scalar_mul_mpq(fmpq_poly_ptr rop, const fmpq_poly_ptr op, const mpq_t x);339340void fmpq_poly_scalar_div_si(fmpq_poly_ptr rop, const fmpq_poly_ptr op, long x);341void fmpq_poly_scalar_div_mpz(fmpq_poly_ptr rop, const fmpq_poly_ptr op, const mpz_t x);342void fmpq_poly_scalar_div_mpq(fmpq_poly_ptr rop, const fmpq_poly_ptr op, const mpq_t x);343344///////////////////////////////////////////////////////////////////////////////345// Multiplication346347void fmpq_poly_mul(fmpq_poly_ptr rop, const fmpq_poly_ptr op1, const fmpq_poly_ptr op2);348349///////////////////////////////////////////////////////////////////////////////350// Division351352void fmpq_poly_floordiv(fmpq_poly_ptr q, const fmpq_poly_ptr a, const fmpq_poly_ptr b);353void fmpq_poly_mod(fmpq_poly_ptr r, const fmpq_poly_ptr a, const fmpq_poly_ptr b);354void fmpq_poly_divrem(fmpq_poly_ptr q, fmpq_poly_ptr r, const fmpq_poly_ptr a, const fmpq_poly_ptr b);355356///////////////////////////////////////////////////////////////////////////////357// Powering358359void fmpq_poly_power(fmpq_poly_ptr rop, const fmpq_poly_ptr op, ulong exp);360361///////////////////////////////////////////////////////////////////////////////362// Greatest common divisor363364void fmpq_poly_gcd(fmpq_poly_ptr rop, const fmpq_poly_ptr a, const fmpq_poly_ptr b);365void fmpq_poly_xgcd(fmpq_poly_ptr rop, fmpq_poly_ptr s, fmpq_poly_ptr t, const fmpq_poly_ptr a, const fmpq_poly_ptr b);366void fmpq_poly_lcm(fmpq_poly_ptr rop, const fmpq_poly_ptr a, const fmpq_poly_ptr b);367368///////////////////////////////////////////////////////////////////////////////369// Derivative370371void fmpq_poly_derivative(fmpq_poly_ptr rop, fmpq_poly_ptr op);372373///////////////////////////////////////////////////////////////////////////////374// Evaluation375376void fmpq_poly_evaluate_mpz(mpq_t rop, fmpq_poly_ptr f, const mpz_t a);377void fmpq_poly_evaluate_mpq(mpq_t rop, fmpq_poly_ptr f, const mpq_t a);378379///////////////////////////////////////////////////////////////////////////////380// Gaussian content381382void fmpq_poly_content(mpq_t rop, const fmpq_poly_ptr op);383void fmpq_poly_primitive_part(fmpq_poly_ptr rop, const fmpq_poly_ptr op);384int fmpq_poly_is_monic(const fmpq_poly_ptr op);385void fmpq_poly_monic(fmpq_poly_ptr rop, const fmpq_poly_ptr op);386387///////////////////////////////////////////////////////////////////////////////388// Resultant389390void fmpq_poly_resultant(mpq_t rop, const fmpq_poly_ptr a, const fmpq_poly_ptr b);391void fmpq_poly_discriminant(mpq_t disc, fmpq_poly_t a);392393///////////////////////////////////////////////////////////////////////////////394// Composition395396void fmpq_poly_compose(fmpq_poly_ptr rop, const fmpq_poly_ptr a, const fmpq_poly_ptr b);397void fmpq_poly_rescale(fmpq_poly_ptr rop, const fmpq_poly_ptr op, const mpq_t x);398399///////////////////////////////////////////////////////////////////////////////400// Square-free401402int fmpq_poly_is_squarefree(const fmpq_poly_ptr op);403404///////////////////////////////////////////////////////////////////////////////405// Subpolynomials406407void fmpq_poly_getslice(fmpq_poly_ptr rop, const fmpq_poly_ptr op, ulong i, ulong j);408void fmpq_poly_left_shift(fmpq_poly_ptr rop, const fmpq_poly_ptr op, ulong n);409void fmpq_poly_right_shift(fmpq_poly_ptr rop, const fmpq_poly_ptr op, ulong n);410void fmpq_poly_truncate(fmpq_poly_ptr rop, const fmpq_poly_ptr op, ulong n);411void fmpq_poly_reverse(fmpq_poly_ptr rop, const fmpq_poly_ptr op, ulong n);412413///////////////////////////////////////////////////////////////////////////////414// String conversion415416void _fmpq_poly_from_list(fmpq_poly_ptr rop, mpq_t * a, ulong n);417int fmpq_poly_from_string(fmpq_poly_ptr rop, const char * s);418char * fmpq_poly_to_string(const fmpq_poly_ptr op);419char * fmpq_poly_to_string_pretty(const fmpq_poly_ptr op, const char * x);420421#ifdef __cplusplus422}423#endif424425#endif426427428429