some more functions in polynomials and permutations
This commit is contained in:
parent
3cf56c3f36
commit
3288e51fba
@ -471,6 +471,48 @@ return a[n];
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAXBINOM 100
|
||||||
|
#define ibidxmaxeven(n) ((n-2)*(n-2)/4)
|
||||||
|
#define ibidx(n,k) (k-2+(n&1?(n-3)*(n-3)/4:(n/2-1)*(n/2-2)))
|
||||||
|
PERM_RANK_TYPE binom(int n, int k)
|
||||||
|
{
|
||||||
|
PERM_RANK_TYPE p,value;
|
||||||
|
register int d;
|
||||||
|
static PERM_RANK_TYPE ibitab[ibidxmaxeven(MAXBINOM)]= /*only nontrivial are stored,
|
||||||
|
zero initialization by compiler assumed*/
|
||||||
|
{
|
||||||
|
6,
|
||||||
|
10,
|
||||||
|
15,20,
|
||||||
|
21,35,
|
||||||
|
28,56,70
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if(k>n||k<0) return(0);
|
||||||
|
if(k>n/2) k=n-k;
|
||||||
|
if(k==0) return(1);
|
||||||
|
if(k==1) return(n);
|
||||||
|
int ind=0;
|
||||||
|
if(n<=MAXBINOM)
|
||||||
|
{
|
||||||
|
ind=ibidx(n,k);
|
||||||
|
if (ibitab[ind]) return ibitab[ind];
|
||||||
|
}
|
||||||
|
/* nonrecurent method used anyway */
|
||||||
|
d=n-k;
|
||||||
|
p=1;
|
||||||
|
for(;n>d;n--) p *= n;
|
||||||
|
value=p/factorial(k);
|
||||||
|
if(n<=MAXBINOM) ibitab[ind]=value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#undef ibidx
|
||||||
|
#undef ibidxmaxeven
|
||||||
|
#undef MAXBINOM
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1599,6 +1641,40 @@ for(int i=1; i<=c.chi.nrows(); ++i)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool CycleIndex<T>::is_valid() const
|
||||||
|
{
|
||||||
|
if(classes.size()!=classsizes.size()) return false;
|
||||||
|
T n=classes[1].sum();
|
||||||
|
for(int i=2; i<=classes.size(); ++i)
|
||||||
|
{
|
||||||
|
if(classes[i].sum()!=n) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Polynomial<T> CycleIndex<T>::substitute(const Polynomial<T> &p, PERM_RANK_TYPE *denom) const
|
||||||
|
{
|
||||||
|
Polynomial<T> r(0);
|
||||||
|
r[0]=(T)0;
|
||||||
|
*denom =0;
|
||||||
|
|
||||||
|
for(int i=1; i<=classes.size(); ++i)
|
||||||
|
{
|
||||||
|
Polynomial<T> term(0);
|
||||||
|
term[0]=(T)1;
|
||||||
|
for(int j=1; j<=classes[i].size(); ++j) if(classes[i][j]) term *= (p.powx(j)).pow((int)classes[i][j]);
|
||||||
|
r += term*classsizes[i];
|
||||||
|
*denom += classsizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* forced instantization in the corresponding object file
|
* forced instantization in the corresponding object file
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -1610,6 +1686,7 @@ template class CompressedPartition<T>; \
|
|||||||
template class Partition<T>; \
|
template class Partition<T>; \
|
||||||
template class YoungTableaux<T>; \
|
template class YoungTableaux<T>; \
|
||||||
template class Sn_characters<T>; \
|
template class Sn_characters<T>; \
|
||||||
|
template class CycleIndex<T>; \
|
||||||
template std::istream & operator>>(std::istream &s, CyclePerm<T> &x); \
|
template std::istream & operator>>(std::istream &s, CyclePerm<T> &x); \
|
||||||
template std::ostream & operator<<(std::ostream &s, const CyclePerm<T> &x); \
|
template std::ostream & operator<<(std::ostream &s, const CyclePerm<T> &x); \
|
||||||
template std::ostream & operator<<(std::ostream &s, const CompressedPartition<T> &x); \
|
template std::ostream & operator<<(std::ostream &s, const CompressedPartition<T> &x); \
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "la_traits.h"
|
#include "la_traits.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
#include "polynomial.h"
|
||||||
|
|
||||||
typedef unsigned long long PERM_RANK_TYPE;
|
typedef unsigned long long PERM_RANK_TYPE;
|
||||||
|
|
||||||
@ -65,6 +66,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern PERM_RANK_TYPE factorial(const int n);
|
extern PERM_RANK_TYPE factorial(const int n);
|
||||||
|
extern PERM_RANK_TYPE binom(int n, int k);
|
||||||
extern PERM_RANK_TYPE longpow(PERM_RANK_TYPE x, int i);
|
extern PERM_RANK_TYPE longpow(PERM_RANK_TYPE x, int i);
|
||||||
|
|
||||||
//permutations represented in the cycle format
|
//permutations represented in the cycle format
|
||||||
@ -212,6 +214,20 @@ NRMat_from1<T> chi; //characters
|
|||||||
bool is_valid() const; //check internal consistency
|
bool is_valid() const; //check internal consistency
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T> class Polynomial; //forward declaration
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class CycleIndex {
|
||||||
|
public:
|
||||||
|
NRVec_from1<CompressedPartition<T> > classes;
|
||||||
|
NRVec_from1<PERM_RANK_TYPE> classsizes;
|
||||||
|
|
||||||
|
CycleIndex(const Sn_characters<T> &rhs): classes(rhs.classes),classsizes(rhs.classsizes) {};
|
||||||
|
bool is_valid() const; //check internal consistency
|
||||||
|
Polynomial<T> substitute(const Polynomial<T> &p, PERM_RANK_TYPE *denom) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
extern std::ostream & operator<<(std::ostream &s, const Sn_characters<T> &c);
|
extern std::ostream & operator<<(std::ostream &s, const Sn_characters<T> &c);
|
||||||
|
|
||||||
|
@ -90,6 +90,16 @@ laerror("roots not implemented for integer polynomials");
|
|||||||
return NRVec<typename LA_traits<int>::complextype>(1);
|
return NRVec<typename LA_traits<int>::complextype>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
NRVec<typename LA_traits<unsigned int>::complextype> Polynomial<unsigned int>::roots() const
|
||||||
|
{
|
||||||
|
laerror("roots not implemented for integer polynomials");
|
||||||
|
return NRVec<typename LA_traits<unsigned int>::complextype>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NRVec<typename LA_traits<T>::complextype> Polynomial<T>::roots() const
|
NRVec<typename LA_traits<T>::complextype> Polynomial<T>::roots() const
|
||||||
{
|
{
|
||||||
@ -107,7 +117,7 @@ NRVec<T> rr(degree());
|
|||||||
int nr=0;
|
int nr=0;
|
||||||
for(int i=0; i<degree(); ++i)
|
for(int i=0; i<degree(); ++i)
|
||||||
{
|
{
|
||||||
if(abs(r[i].imag())<thr)
|
if(MYABS(r[i].imag())<thr)
|
||||||
{
|
{
|
||||||
rr[nr++] = r[i].real();
|
rr[nr++] = r[i].real();
|
||||||
}
|
}
|
||||||
@ -151,7 +161,7 @@ T x=x0;
|
|||||||
for(int i=0; i<maxit; ++i)
|
for(int i=0; i<maxit; ++i)
|
||||||
{
|
{
|
||||||
T v=value(*this,x);
|
T v=value(*this,x);
|
||||||
if(abs(v)<thr) break;
|
if(MYABS(v)<thr) break;
|
||||||
x -= v/value(d,x);
|
x -= v/value(d,x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +195,15 @@ laerror("SVD gcd only for floating point numbers");
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Polynomial<unsigned int> svd_gcd(const Polynomial<unsigned int> &p, const Polynomial<unsigned int> &q, const typename LA_traits<unsigned int>::normtype thr)
|
||||||
|
{
|
||||||
|
laerror("SVD gcd only for floating point numbers");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Polynomial<T> svd_gcd(const Polynomial<T> &p, const Polynomial<T> &q, const typename LA_traits<T>::normtype thr)
|
Polynomial<T> svd_gcd(const Polynomial<T> &p, const Polynomial<T> &q, const typename LA_traits<T>::normtype thr)
|
||||||
{
|
{
|
||||||
@ -202,12 +221,54 @@ int d=big.degree()+small.degree()-rank;
|
|||||||
return poly_gcd(big,small,thr,d);
|
return poly_gcd(big,small,thr,d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Polynomial<T> Polynomial<T>::pow(const int n) const
|
||||||
|
{
|
||||||
|
int i=n;
|
||||||
|
if(i<0) laerror("negative exponent in polynomial::pow");
|
||||||
|
if(i==0) {Polynomial<T> r(0); r[0]=(T)1; return r;}
|
||||||
|
if(i==1) return *this;
|
||||||
|
Polynomial<T>y,z;
|
||||||
|
z= *this;
|
||||||
|
while(!(i&1))
|
||||||
|
{
|
||||||
|
z = z*z;
|
||||||
|
i >>= 1;
|
||||||
|
}
|
||||||
|
y=z;
|
||||||
|
while((i >>= 1)/*!=0*/)
|
||||||
|
{
|
||||||
|
z = z*z;
|
||||||
|
if(i&1) y = y*z;
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Polynomial<T> Polynomial<T>::powx(const int i) const
|
||||||
|
{
|
||||||
|
if(i<0) laerror("negative exponent in polynomial::pow");
|
||||||
|
if(i==0) {Polynomial<T> r(0); r[0]= this->sum(); return r;}
|
||||||
|
if(i==1) return *this;
|
||||||
|
Polynomial<T> r(i*this->degree());
|
||||||
|
r.clear();
|
||||||
|
for(int j=0; j<=this->degree(); ++j) r[j*i] = (*this)[j];
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Polynomial<T>::binomial(const int n)
|
||||||
|
{
|
||||||
|
resize(n,false);
|
||||||
|
for(int i=0; i<=n; ++i) (*this)[i] = (T) binom(n,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
* forced instantization in the corresponding object file
|
* forced instantization in the corresponding object file
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
template class Polynomial<int>;
|
template class Polynomial<int>;
|
||||||
|
template class Polynomial<unsigned int>;
|
||||||
template class Polynomial<double>;
|
template class Polynomial<double>;
|
||||||
template class Polynomial<std::complex<double> >;
|
template class Polynomial<std::complex<double> >;
|
||||||
|
|
||||||
@ -220,6 +281,7 @@ template Polynomial<T> svd_gcd(const Polynomial<T> &p, const Polynomial<T> &q, c
|
|||||||
|
|
||||||
|
|
||||||
INSTANTIZE(int)
|
INSTANTIZE(int)
|
||||||
|
INSTANTIZE(unsigned int)
|
||||||
INSTANTIZE(double)
|
INSTANTIZE(double)
|
||||||
INSTANTIZE(std::complex<double>)
|
INSTANTIZE(std::complex<double>)
|
||||||
|
|
||||||
|
17
polynomial.h
17
polynomial.h
@ -26,6 +26,13 @@
|
|||||||
|
|
||||||
namespace LA {
|
namespace LA {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline typename LA_traits<T>::normtype MYABS(const T &x) {return abs(x);}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline unsigned int MYABS(const unsigned int &x) {return x;}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Polynomial : public NRVec<T> {
|
class Polynomial : public NRVec<T> {
|
||||||
public:
|
public:
|
||||||
@ -72,12 +79,13 @@ public:
|
|||||||
for(int i=0; i<=rhs.degree(); ++i) for(int j=0; j<=degree(); ++j) r[i+j] += rhs[i]*(*this)[j];
|
for(int i=0; i<=rhs.degree(); ++i) for(int j=0; j<=degree(); ++j) r[i+j] += rhs[i]*(*this)[j];
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
Polynomial& operator*=(const Polynomial &rhs) {*this = (*this)*rhs; return *this;};
|
||||||
void simplify(const typename LA_traits<T>::normtype thr=0)
|
void simplify(const typename LA_traits<T>::normtype thr=0)
|
||||||
{
|
{
|
||||||
NOT_GPU(*this);
|
NOT_GPU(*this);
|
||||||
this->copyonwrite();
|
this->copyonwrite();
|
||||||
int n=degree();
|
int n=degree();
|
||||||
while(n>0 && abs((*this)[n])<=thr) --n;
|
while(n>0 && MYABS((*this)[n])<=thr) --n;
|
||||||
resize(n,true);
|
resize(n,true);
|
||||||
};
|
};
|
||||||
void normalize() {if((*this)[degree()]==(T)0) laerror("zero coefficient at highest degree - simplify first"); *this /= (*this)[degree()];};
|
void normalize() {if((*this)[degree()]==(T)0) laerror("zero coefficient at highest degree - simplify first"); *this /= (*this)[degree()];};
|
||||||
@ -148,10 +156,13 @@ public:
|
|||||||
NRVec<typename LA_traits<T>::complextype> roots() const; //implemented for complex<double> and double only
|
NRVec<typename LA_traits<T>::complextype> roots() const; //implemented for complex<double> and double only
|
||||||
NRVec<T> realroots(const typename LA_traits<T>::normtype thr) const;
|
NRVec<T> realroots(const typename LA_traits<T>::normtype thr) const;
|
||||||
T newton(const T x0, const typename LA_traits<T>::normtype thr=1e-14, const int maxit=1000) const; //solve root from the guess
|
T newton(const T x0, const typename LA_traits<T>::normtype thr=1e-14, const int maxit=1000) const; //solve root from the guess
|
||||||
|
Polynomial pow(const int i) const; //integer power
|
||||||
|
Polynomial powx(const int i) const; //substitute x^i for x in the polynomial
|
||||||
|
void binomial(const int n); //(1+x)^n
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//this is very general, can be used also for nesting polynomials
|
//this is very general, can be used also for composition (nesting) of polynomials
|
||||||
//for an alternative algorithm which minimizes number of multiplications cf. also matexp.h
|
//for an alternative algorithm which minimizes number of multiplications cf. also matexp.h
|
||||||
template <typename T, typename C>
|
template <typename T, typename C>
|
||||||
C value(const Polynomial<T> &p, const C &x)
|
C value(const Polynomial<T> &p, const C &x)
|
||||||
@ -199,6 +210,8 @@ return p;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
extern Polynomial<T> lagrange_interpolation(const NRVec<T> &x, const NRVec<T> &y);
|
extern Polynomial<T> lagrange_interpolation(const NRVec<T> &x, const NRVec<T> &y);
|
||||||
|
|
||||||
|
22
t.cc
22
t.cc
@ -2158,13 +2158,19 @@ if(tot!=partitions(n)) laerror("internal error in partition generation or enumer
|
|||||||
if(space_dim!=longpow(unitary_n,n)) {cout<<space_dim<<" "<<ipow(unitary_n,n)<<endl;laerror("integer overflow or internal error in space dimensions");}
|
if(space_dim!=longpow(unitary_n,n)) {cout<<space_dim<<" "<<ipow(unitary_n,n)<<endl;laerror("integer overflow or internal error in space dimensions");}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0)
|
if(1)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
cin >>n ;
|
cin >>n ;
|
||||||
Sn_characters<int> Sn(n);
|
Sn_characters<int> Sn(n);
|
||||||
cout <<Sn;
|
cout <<Sn;
|
||||||
if(!Sn.is_valid()) laerror("internal error in Sn character calculation");
|
if(!Sn.is_valid()) laerror("internal error in Sn character calculation");
|
||||||
|
Polynomial<int> p(1);
|
||||||
|
p[0]=p[1]=1;
|
||||||
|
CycleIndex<int> c(Sn);
|
||||||
|
PERM_RANK_TYPE d;
|
||||||
|
Polynomial<int> pp=c.substitute(p,&d);
|
||||||
|
for(int i=0; i<=p.size(); ++i) if(d!=pp[i]) laerror("error in cycle index");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0)
|
if(0)
|
||||||
@ -2242,7 +2248,7 @@ Polynomial<double>pp=q.derivative(2);
|
|||||||
cout<<"test deriv. "<<(pp-p).norm()<<endl;
|
cout<<"test deriv. "<<(pp-p).norm()<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1)
|
if(0)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
cin >>n;
|
cin >>n;
|
||||||
@ -2268,5 +2274,17 @@ cout <<"test gcd "<<(rr-rrr).norm()<<endl;
|
|||||||
cout <<"test svdgcd "<<(rr-rrrr).norm()<<endl;
|
cout <<"test svdgcd "<<(rr-rrrr).norm()<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(0)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
cin >>n;
|
||||||
|
Polynomial<double> p;
|
||||||
|
p.binomial(n);
|
||||||
|
Polynomial<double> q(1);
|
||||||
|
q[0]=q[1]=1.;
|
||||||
|
Polynomial<double> qq=q.pow(n);
|
||||||
|
cout <<"test binom "<<(p-qq).norm()<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user