/* -*- mode:C++ ; compile-command: "g++ -I.. -g -c gausspol.cc" -*- */
/*
* Copyright (C) 2000,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see .
*/
#ifndef _GIAC_GAUSSPOL_H_
#define _GIAC_GAUSSPOL_H_
#include "first.h"
#include "poly.h"
#include "gen.h"
#ifdef HAVE_PTHREAD_H
#include
#endif
#ifndef NO_NAMESPACE_GIAC
namespace giac {
#endif // ndef NO_NAMESPACE_GIAC
#ifdef USE_GMP_REPLACEMENTS
#undef HAVE_GMPXX_H
#undef HAVE_LIBMPFR
#endif
extern const int primes[100] ;
class nfactor {
public:
gen fact;
int mult;
nfactor():fact(1),mult(0) {}
nfactor(const nfactor &n) : fact(n.fact),mult(n.mult) {}
nfactor(const gen & n, int m) : fact(n),mult(m) {}
};
std::vector trivial_n_factor(gen &n);
vecteur cyclotomic(int n);
// gen pow(const gen & n,int k);
typedef std::vector< monomial > monomial_v;
typedef tensor polynome;
// function on polynomials
polynome gen2polynome(const gen & e,int dim);
// check type of coefficients
int coefftype(const polynome & p,gen & coefft);
// remove MODulo coefficients
void unmodularize(const polynome & p,polynome & res);
polynome unmodularize(const polynome & p);
void modularize(polynome & d,const gen & m);
// remove EXT, also checks that pmin is the min poly
bool unext(const polynome & p,const gen & pmin,polynome & res);
bool ext(polynome & res,const gen & pmin);
void ext(const polynome & p,const gen & pmin,polynome & res);
// arithmetic
bool is_one(const polynome & p);
bool operator < (const polynome & f,const polynome & g);
bool operator < (const facteur & f,const facteur & g);
polynome firstcoeff(const polynome & p);
void Add_gen ( std::vector< monomial >::const_iterator & a,
std::vector< monomial >::const_iterator & a_end,
std::vector< monomial >::const_iterator & b,
std::vector< monomial >::const_iterator & b_end,
std::vector< monomial > & new_coord,
bool (* is_strictly_greater)( const index_m &, const index_m &)) ;
polynome operator + (const polynome & th,const polynome & other);
void Sub_gen ( std::vector< monomial >::const_iterator & a,
std::vector< monomial >::const_iterator & a_end,
std::vector< monomial >::const_iterator & b,
std::vector< monomial >::const_iterator & b_end,
std::vector< monomial > & new_coord,
bool (* is_strictly_greater)( const index_m &, const index_m &)) ;
polynome operator - (const polynome & th,const polynome & other);
// Fast multiplication using hash maps, might also use an int for reduction
// but there is no garantee that res is smod-ed modulo reduce
// Use reduce=0 for non modular
void mulpoly (const polynome & th, const polynome & other,polynome & res,const gen & reduce);
polynome operator * (const polynome & th, const polynome & other) ;
polynome & operator *= (polynome & th, const polynome & other) ;
void Mul_gen ( std::vector< monomial >::const_iterator & ita,
std::vector< monomial >::const_iterator & ita_end,
std::vector< monomial >::const_iterator & itb,
std::vector< monomial >::const_iterator & itb_end,
std::vector< monomial > & new_coord,
bool (* is_strictly_greater)( const index_t &, const index_t &),
const std::pointer_to_binary_function < const monomial &, const monomial &, bool> m_is_greater
) ;
void mulpoly(const polynome & th,const gen & fact,polynome & res);
polynome operator * (const polynome & th, const gen & fact) ;
inline polynome operator * (const gen & fact, const polynome & th){ return th*fact; }
// a*b+c*d
gen foisplus(const polynome & a,const polynome & b,const polynome & c,const polynome & d);
gen foisplus(const gen & a,const gen & b,const gen & c,const gen & d);
polynome operator - (const polynome & th) ;
polynome operator / (const polynome & th,const polynome & other);
polynome operator / (const polynome & th,const gen & fact );
polynome operator % (const polynome & th,const polynome & other);
polynome operator % (const polynome & th, const gen & modulo);
polynome re(const polynome & th);
polynome im(const polynome & th);
polynome conj(const polynome & th);
polynome poly1_2_polynome(const vecteur & v, int dimension);
void polynome2poly1(const polynome & p,int var,vecteur & v);
vecteur polynome12poly1(const polynome & p);
int inner_POLYdim(const vecteur & v);
vecteur polynome2poly1(const polynome & p,int var);
vecteur polynome2poly1(const polynome & p); // for algebraic ext.
gen polynome2poly1(const gen & e,int var);
void poly12polynome(const vecteur & v, int var,polynome & p,int dimension=0);
polynome poly12polynome(const vecteur & v,int var,int dimension=0);
polynome poly12polynome(const vecteur & v);
gen untrunc(const gen & e,int degree,int dimension);
gen vecteur2polynome(const vecteur & v,int dimension);
bool divrem1(const polynome & a,const polynome & b,polynome & quo,polynome & r,int exactquo=0,bool allowrational=false) ;
bool divrem (const polynome & th, const polynome & other, polynome & quo, polynome & rem, bool allowrational = false );
bool divremmod (const polynome & th,const polynome & other, const gen & modulo,polynome & quo, polynome & rem);
bool exactquotient(const polynome & a,const polynome & b,polynome & quo,bool allowrational=true);
bool powpoly (const polynome & th, int u,polynome & res);
polynome pow(const polynome & th,int n);
bool is_positive(const polynome & p);
polynome pow(const polynome & p,const gen & n);
polynome powmod(const polynome &p,int n,const gen & modulo);
polynome gcd(const polynome & p,const polynome & q);
void gcd(const polynome & p,const polynome & q,polynome & d);
void lcmdeno(const polynome & p, gen & res);
gen lcoeffn(const polynome & p);
gen lcoeff1(const polynome & p);
polynome ichinrem(const polynome &p,const polynome & q,const gen & pmod,const gen & qmod);
// set i to i+(j-i)*B mod A, inplace operation
void ichrem_smod_inplace(mpz_t * Az,mpz_t * Bz,mpz_t * iz,mpz_t * tmpz,gen & i,const gen & j);
polynome resultant(const polynome & p,const polynome & q);
bool resultant_sylvester(const polynome &p,const polynome &q,matrice & S,polynome & res);
bool resultant_sylvester(const polynome &p,const polynome &q,vecteur &pv,vecteur &qv,matrice & S,gen & determinant);
polynome lgcd(const polynome & p);
gen ppz(polynome & p,bool divide=true);
void lgcdmod(const polynome & p,const gen & modulo,polynome & pgcd);
polynome gcdmod(const polynome &p,const polynome & q,const gen & modulo);
polynome content1mod(const polynome & p,const gen & modulo,bool setdim=true);
void contentgcdmod(const polynome &p, const polynome & q, const gen & modulo, polynome & cont,polynome & prim);
polynome pp1mod(const polynome & p,const gen & modulo);
// modular gcd via PSR, used when not enough eval points available
// a and b must be primitive and will be scratched
void psrgcdmod(polynome & a,polynome & b,const gen & modulo,polynome & prim);
// Find non zeros coeffs of p, res contains the positions of non-0 coeffs
int find_nonzero(const polynome & p,index_t & res);
polynome pzadic(const polynome &p,const gen & n);
bool gcd_modular_algo(polynome &p,polynome &q, polynome &d,bool compute_cof);
bool listmax(const polynome &p,gen & n );
bool gcdheu(const polynome &p,const polynome &q, polynome & p_simp, gen & np_simp, polynome & q_simp, gen & nq_simp, polynome & d, gen & d_content ,bool skip_test=false,bool compute_cofactors=true);
polynome gcdpsr(const polynome &p,const polynome &q,int gcddeg=0);
void simplify(polynome & p,polynome & q,polynome & p_gcd);
polynome simplify(polynome &p,polynome &q);
void egcdlgcd(const polynome &p1, const polynome & p2, polynome & u,polynome & v,polynome & d);
void egcdpsr(const polynome &p1, const polynome & p2, polynome & u,polynome & v,polynome & d);
void egcd(const polynome &p1, const polynome & p2, polynome & u,polynome & v,polynome & d);
// Input a,b,c,u,v,d such that a*u+b*v=d,
// Output u,v,C such that a*u+b*v=c*C
void egcdtoabcuv(const tensor & a,const tensor &b, const tensor &c, tensor &u,tensor &v, tensor & d, tensor & C);
bool findabcdelta(const polynome & p,polynome & a,polynome &b,polynome & c,polynome & delta);
bool findde(const polynome & p,polynome & d,polynome &e);
factorization sqff(const polynome &p );
// factorize a square-free univariate polynomial
bool sqfffactor(const polynome &p, vectpoly & v,bool with_sqrt,bool test_composite,bool complexmode);
bool sqff_evident(const polynome & p,factorization & f,bool withsqrt,bool complexmode);
// factorization over Z[i]
bool cfactor(const polynome & p, gen & an,factorization & f,bool withsqrt,gen & extra_div);
// add a dimension in front of pcur for algebraic extension variable
bool algext_convert(const polynome & pcur,const gen & e,polynome & p_y);
// convert minimal polynomial of algebraic extension
void algext_vmin2pmin(const vecteur & v_mini,polynome & p_mini);
// factorization over an algebraic extension
// the main variable of G is the algebraic extension variable
// the minimal polynomial of this variable is p_mini
// G is assumed to be square-free
// See algorithm 3.6.4 in Henri Cohen book starting at step 3
bool algfactor(const polynome & G,const polynome & p_mini,int & k,factorization & f,bool complexmode,gen & extra_div,polynome & Gtry);
// sqff factorization over a finite field
factorization squarefree_fp(const polynome & p,unsigned n,unsigned exposant);
// univariate factorization over a finite field, once sqff
bool sqff_ffield_factor(const factorization & sqff_f,int n,environment * env,factorization & f);
// p is primitive wrt the main var
bool mod_factor(const polynome & p_orig,polynome & p_content,int n,factorization & f);
// factorization over Z[e] where e is an algebraic extension
bool ext_factor(const polynome &p,const gen & e,gen & an,polynome & p_content,factorization & f,bool complexmode,gen &extra_div);
// factorization over Z[coeff_of_p]
bool factor(const polynome &p,polynome & p_content,factorization & f,bool isprimitive,bool withsqrt,bool complexmode,const gen & divide_by_an,gen & extra_div);
void unitarize(const polynome &pcur, polynome &unitaryp, polynome & an);
polynome ununitarize(const polynome & unitaryp, const polynome & an);
void partfrac(const polynome & num, const polynome & den, const std::vector< facteur< polynome > > & v , std::vector < pf > & pfde_VECT, polynome & ipnum, polynome & ipden, bool rational=true );
pf intreduce_pf(const pf & p_cst, std::vector< pf > & intde_VECT ,bool residue=false);
// Sturm sequences
vecteur vector_of_polynome2vecteur(const vectpoly & v);
vecteur sturm_seq(const polynome & p,polynome & cont);
// prototype of factorization of univariate sqff unitary polynomial
// provided e.g. by smodular
bool factorunivsqff(const polynome & q,environment * env,vectpoly & v,int & ithprime,int debug,int modfactor_primes);
// find linear factor only
int linearfind(const polynome & q,environment * env,polynome & qrem,vectpoly & v,int & ithprime);
// prototype of modular 1-d gcd algorithm
bool gcd_modular_algo1(polynome &p,polynome &q,polynome &d,bool compute_cof);
polynome smod(const polynome & th, const gen & modulo);
void smod(const polynome & th, const gen & modulo,polynome & res);
bool gcdmod_dim1(const polynome &p,const polynome & q,const gen & modulo,polynome & d,polynome & pcof,polynome & qcof,bool compute_cof,bool & real);
// evaluate p at v by replacing the last variables of p with values of v
gen peval(const polynome & p,const vecteur & v,const gen &m,bool simplify_at_end=false,std::vector * pptr=0);
int total_degree(const polynome & p);
// build a multivariate poly
// with normal coeff from a multivariate poly with multivariate poly coeffs
polynome unsplitmultivarpoly(const polynome & p,int inner_dim);
polynome splitmultivarpoly(const polynome & p,int inner_dim);
polynome split(const polynome & p,int inner_dim);
template
bool convert_myint(const polynome & p,const index_t & deg,std::vector< T_unsigned > & v){
typename std::vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
v.clear();
v.reserve(itend-it);
U u;
my_mpz tmp;
index_t::const_iterator itit,ditbeg=deg.begin(),ditend=deg.end(),dit;
T_unsigned gu;
for (;it!=itend;++it){
u=0;
itit=it->index.begin();
for (dit=ditbeg;dit!=ditend;++itit,++dit)
u=u*unsigned(*dit)+unsigned(*itit);
gu.u=u;
if (it->value.type==_ZINT)
mpz_set(gu.g.ptr,*it->value._ZINTptr);
else {
if (it->value.type!=_INT_)
return false;
mpz_set_si(gu.g.ptr,it->value.val);
}
v.push_back(gu);
}
return true;
}
#ifdef HAVE_GMPXX_H
template
bool convert_myint(const polynome & p,const index_t & deg,std::vector< T_unsigned > & v){
typename std::vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
v.clear();
v.reserve(itend-it);
U u;
index_t::const_iterator itit,ditbeg=deg.begin(),ditend=deg.end(),dit;
for (;it!=itend;++it){
u=0;
itit=it->index.begin();
for (dit=ditbeg;dit!=ditend;++itit,++dit)
u=u*unsigned(*dit)+unsigned(*itit);
T_unsigned gu;
gu.u=u;
if (it->value.type==_ZINT){
mpz_set(gu.g.get_mpz_t(),*it->value._ZINTptr);
}
else {
if (it->value.type!=_INT_)
return false;
gu.g=it->value.val;
}
v.push_back(gu);
}
return true;
}
#endif
template int coeff_type(const std::vector< T_unsigned > & p,unsigned & maxint){
maxint=0;
typename std::vector< T_unsigned >::const_iterator it=p.begin(),itend=p.end();
if (it==itend)
return -1;
int t=it->g.type,tt;
register int tmp;
for (++it;it!=itend;++it){
tt=it->g.type;
if (tt!=t)
return -1;
if (!tt){
if (it->g.val>0)
tmp=it->g.val;
else
tmp=-it->g.val;
if (maxint
bool convert_double(const polynome & p,const index_t & deg,std::vector< T_unsigned > & v){
typename std::vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
v.clear();
v.reserve(itend-it);
T_unsigned gu;
U u;
index_t::const_iterator itit,ditbeg=deg.begin(),ditend=deg.end(),dit;
for (;it!=itend;++it){
u=0;
itit=it->index.begin();
for (dit=ditbeg;dit!=ditend;++itit,++dit)
u=u*unsigned(*dit)+unsigned(*itit);
gu.u=u;
if (it->value.type!=_DOUBLE_)
return false;
gu.g=it->value._DOUBLE_val;
v.push_back(gu);
}
return true;
}
template
bool convert_int32(const polynome & p,const index_t & deg,std::vector< T_unsigned > & v,int modulo=0){
typename std::vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
v.clear();
v.reserve(itend-it);
U u;
index_t::const_iterator itit,oldit,ititend,ditbeg=deg.begin(),ditend=deg.end(),dit;
for (;it!=itend;++it){
u=0;
oldit=itit=it->index.begin();
for (dit=ditbeg;dit!=ditend;++itit,++dit)
u=u*unsigned(*dit)+unsigned(*itit);
if (it->value.type==_INT_){
if (modulo)
v.push_back(T_unsigned(it->value.val % modulo,u));
else
v.push_back(T_unsigned(it->value.val,u));
}
else {
if (modulo && it->value.type==_ZINT)
v.push_back(T_unsigned(smod(it->value,modulo).val,u));
else
return false;
}
int nterms=*(itit-1);
if (nterms<=1 || nterms>=itend-it)
continue;
itit = (it+nterms)->index.begin();
ititend = itit + p.dim-1;
if (*(ititend))
continue;
for (;itit!=ititend;++oldit,++itit){
if (*itit!=*oldit)
break;
}
if (itit!=ititend)
continue;
// for dense poly, make all terms with the same x1..xn-1 powers
for (;nterms;--nterms){
++it;
--u;
if (it->value.type==_INT_){
if (modulo)
v.push_back(T_unsigned(it->value.val % modulo,u));
else
v.push_back(T_unsigned(it->value.val,u));
}
else {
if (modulo && it->value.type==_ZINT)
v.push_back(T_unsigned(smod(it->value,modulo).val,u));
else
return false;
}
}
}
return true;
}
template
bool convert_int(const polynome & p,const index_t & deg,std::vector< T_unsigned > & v,longlong & maxp){
typename std::vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
v.clear();
v.reserve(itend-it);
T_unsigned gu;
U u;
maxp=0;
longlong tmp;
mpz_t tmpz;
mpz_init(tmpz);
index_t::const_iterator itit,ditbeg=deg.begin(),ditend=deg.end(),dit;
for (;it!=itend;++it){
u=0;
itit=it->index.begin();
for (dit=ditbeg;dit!=ditend;++itit,++dit)
u=u*unsigned(*dit)+unsigned(*itit);
gu.u=u;
if (it->value.type==_INT_)
gu.g=it->value.val;
else {
if (it->value.type!=_ZINT || mpz_sizeinbase(*it->value._ZINTptr,2)>62){
mpz_clear(tmpz);
return false;
}
mpz2longlong(it->value._ZINTptr,&tmpz,gu.g);
}
tmp=gu.g>0?gu.g:-gu.g;
if (tmp>maxp)
maxp=tmp;
v.push_back(gu);
}
mpz_clear(tmpz);
return true;
}
#ifdef INT128
template
bool convert_int(const polynome & p,const index_t & deg,std::vector< T_unsigned > & v,int128_t & maxp){
typename std::vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
v.clear();
v.reserve(itend-it);
T_unsigned gu;
U u;
maxp=0;
int128_t tmp;
mpz_t tmpz;
mpz_init(tmpz);
index_t::const_iterator itit,ditbeg=deg.begin(),ditend=deg.end(),dit;
for (;it!=itend;++it){
u=0;
itit=it->index.begin();
for (dit=ditbeg;dit!=ditend;++itit,++dit)
u=u*unsigned(*dit)+unsigned(*itit);
gu.u=u;
if (it->value.type==_INT_)
gu.g=it->value.val;
else {
if (it->value.type!=_ZINT || mpz_sizeinbase(*it->value._ZINTptr,2)>124){
mpz_clear(tmpz);
return false;
}
mpz2int128(it->value._ZINTptr,&tmpz,gu.g);
}
tmp=gu.g>0?gu.g:-gu.g;
if (tmp>maxp)
maxp=tmp;
v.push_back(gu);
}
mpz_clear(tmpz);
return true;
}
#endif
template void convert_longlong(const std::vector< T_unsigned > & p,std::vector< T_unsigned > & pd){
typename std::vector< T_unsigned >::const_iterator it=p.begin(),itend=p.end();
pd.reserve(itend-it);
for (;it!=itend;++it)
pd.push_back(T_unsigned(it->g.val,it->u));
}
template void convert_from(const std::vector< T_unsigned > & p,std::vector< T_unsigned > & pd){
typename std::vector< T_unsigned >::const_iterator it=p.begin(),itend=p.end();
pd.reserve(itend-it);
for (;it!=itend;++it){
if (it->g)
pd.push_back(T_unsigned(gen(it->g),it->u));
}
}
// mode=0: fill both, =1 fill the gen part, =2 fill the index_m part
template
void convert_from(typename std::vector< T_unsigned >::const_iterator it,typename std::vector< T_unsigned >::const_iterator itend,const index_t & deg,typename std::vector< monomial >::iterator jt,int mode=0){
if (mode==1){
for (;it!=itend;++jt,++it){
jt->value=gen(it->g);
}
return;
}
index_t::const_reverse_iterator ditbeg=deg.rbegin(),ditend=deg.rend(),dit;
int pdim=int(deg.size());
U u,prevu=0;
int k;
int count=0;
#if defined(GIAC_NO_OPTIMIZATIONS) || ((defined(VISUALC) || defined(__APPLE__)) && !defined(GIAC_VECTOR)) || defined __clang__ // || defined NSPIRE
if (0){ count=0; }
#else
if (pdim<=POLY_VARS){
deg_t i[POLY_VARS+1];
i[0]=2*pdim+1;
deg_t * iitbeg=i+1,*iit,*iitback=i+pdim,*iitbackm1=iitback-1;
for (iit=iitbeg;iit!=iitback;++iit)
*iit=0;
*iitback=0;
for (--prevu;it!=itend;++it,++jt){
u=it->u;
if (prevu<=u+*iitback){
*iitback -= deg_t(prevu-u);
prevu=u;
}
else {
if (pdim>1 && (*iitbackm1)>0 && prevu<=u+*ditbeg+*iitback){
--(*iitbackm1);
*iitback += deg_t((u+(*ditbeg))-prevu);
prevu=u;
}
else
{
prevu=u;
for (k=pdim,dit=ditbeg;dit!=ditend;++dit,--k){
// qr=div(u,*dit);
i[k]=u % (*dit); // qr.rem;
u= u / (*dit); // qr.quot;
count += pdim;
}
}
}
jt->index=i;
if (mode)
continue;
jt->value=gen(it->g);
// p.coord.push_back(monomial(gen(it->g),i));
}
}
#endif
else {
index_t i(pdim);
index_t::iterator iitbeg=i.begin(),iitback=i.end()-1,iitbackm1=iitback-1;
for (--prevu;it!=itend;++it,++jt){
u=it->u;
if (prevu<=u+*iitback){
*iitback -= short(prevu-u);
prevu=u;
}
else {
if (pdim>1 && (*iitbackm1)>0 && prevu<=u+*ditbeg+*iitback){
--(*iitbackm1);
*iitback += short((u+(*ditbeg))-prevu);
prevu=u;
// cerr << "/" << u << ":" << i << endl;
}
else
{
prevu=u;
for (k=pdim-1,dit=ditbeg;dit!=ditend;++dit,--k){
// qr=div(u,*dit);
i[k]=u % (*dit); // qr.rem;
u= u / (*dit); // qr.quot;
count += pdim;
// i[k]=u % unsigned(*dit);
// u = u/unsigned(*dit);
}
}
}
jt->index=i;
if (mode)
continue;
jt->value=gen(it->g);
// p.coord.push_back(monomial(gen(it->g),i));
}
}
if (debug_infolevel>5)
CERR << "Divisions: " << count << std::endl;
}
template
struct convert_t {
typename std::vector< T_unsigned >::const_iterator it,itend;
const index_t * degptr;
typename std::vector< monomial >::iterator jt;
int mode;
};
template
void * do_convert_from(void * ptr){
convert_t * argptr = (convert_t *) ptr;
convert_from(argptr->it,argptr->itend,*argptr->degptr,argptr->jt,argptr->mode);
return 0;
}
extern int threads;
template
void convert_from(const std::vector< T_unsigned > & v,const index_t & deg,polynome & p,bool threaded=false){
typename std::vector< T_unsigned >::const_iterator it=v.begin(),itend=v.end();
p.dim=int(deg.size());
// p.coord.clear(); p.coord.reserve(itend-it);
p.coord=std::vector< monomial >(itend-it);
std::vector< monomial >::iterator jt=p.coord.begin();
int nthreads=threads;
if (nthreads==1 || !threaded || p.dim>POLY_VARS){
convert_from(it,itend,deg,jt,0);
return;
}
#if defined(HAVE_PTHREAD_H) && !defined(EMCC) // && !defined(__clang__)
unsigned taille=itend-it;
if (nthreads>1
&& int(taille)>nthreads*1000
){
pthread_t tab[nthreads];
std::vector< convert_t > arg(nthreads);
for (int i=0;i tmp={it+i*(taille/nthreads),it+(i+1)*taille/nthreads,°,jt+i*(taille/nthreads),0};
if (i==nthreads-1){
tmp.itend=itend;
convert_from(tmp.it,tmp.itend,deg,tmp.jt,tmp.mode);
}
else {
arg[i]=tmp;
int res=pthread_create(&tab[i],(pthread_attr_t *) NULL,do_convert_from,(void *) &arg[i]);
if (res)
convert_from(tmp.it,tmp.itend,deg,tmp.jt,tmp.mode);
}
}
for (int i=0;i1)
#endif
convert_from(it,itend,deg,jt,0);
}
#ifndef NO_NAMESPACE_GIAC
} // namespace giac
#endif // ndef NO_NAMESPACE_GIAC
#endif // _GIAC_GAUSSPOL_H_