00001 #ifndef realroot_SOLVE_SBDSLV_BINOMIALS_H
00002 #define realroot_SOLVE_SBDSLV_BINOMIALS_H
00003
00004 #include <vector>
00005 #include <assert.h>
00006
00007 namespace mmx {
00008
00009 #ifndef WITH_POW
00010 #define WITH_POW
00011 template<class T>
00012 T pow(const T& a, int i)
00013 {
00014 assert(i>=0);
00015 if(i == 1) return a;
00016 if(i > 0)
00017 {
00018 if (a == T(1)) return a;
00019 if (a == T(-1)) return (i % 2 == 0) ? T(1) : T(-1);
00020 T y(a);
00021 T z(1);
00022 unsigned int n = i;
00023 unsigned int m;
00024 while (n > 0) {
00025 m = n / 2;
00026 if (n %2 )
00027 {
00028 z *= y;
00029 }
00030 y = y * y;
00031 n = m;
00032 }
00033 return z;
00034 }
00035 return T(1);
00036 }
00037 #endif //WITH_POW
00038
00040 template <typename T> T factorial(int n)
00041 {
00042 T r=1;
00043 for (int i=2;i<=n;i++) r*=n;
00044 return(r);
00045 }
00046
00047
00048 #ifndef WITH_BINOMIAL
00049 #define WITH_BINOMIAL
00050
00052 template <typename T> T binomial(int n, int p)
00053 {
00054 T n1=1;
00055
00056 if(p!=0)
00057 {
00058 if((n-p)<p) p=n-p;
00059 int n2=n;
00060 for(int i=1;i<=p;i++,n2--) n1=n1*n2/T(i);
00061 }
00062
00063 return(n1);
00064 }
00065 #endif //WITH_BINOMIAL
00066
00067 template<typename C>
00068 struct binomials {
00069 static binomials default_;
00070 std::vector<int> offs;
00071 std::vector<C> data;
00072 binomials(const binomials& b):offs(b.offs),data(b.data) {}
00073 binomials();
00074
00075 const C* operator[]( int d );
00076 const C& operator()( int i, int j ) { return (*this)[i][j]; };
00077 };
00078
00079
00080
00081 template<class C>
00082 binomials<C>::binomials() : offs(2), data(3)
00083 {
00084 offs[0] = 0; data[0] = 1;
00085 offs[1] = 1; data[offs[1]] = 1; data[offs[1]+1] = 1;
00086 };
00087
00088 template<class C> binomials<C> binomials<C>::default_;
00089
00090 template<class C>
00091 const C* binomials<C>::operator[]( int d )
00092 {
00093 int s,j,x;
00094 if ( (s=offs.size()) > d ) return &*(data.begin())+offs[d];
00095 for ( x = 0, j = s; j <= d; x += j+1, j ++ ) {}
00096 offs.resize(d+1);
00097 data.resize(data.size()+x);
00098 for ( j = s; j <= d; j ++ )
00099 {
00100 offs[j] = offs[j-1] + j;
00101 for ( int i = 0; i < j-1; i ++ )
00102 data[offs[j]+i+1] = data[offs[j-1]+i] + data[offs[j-1]+i+1];
00103 data[offs[j]] = data[offs[j]+j] = 1;
00104 };
00105 return &*(data.begin())+offs[d];
00106 };
00107
00108 }
00109
00110 #endif