realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/binomials.hpp
Go to the documentation of this file.
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   // return the list [ binomial(d,i) ], for i = 0..d
00075   const C* operator[]( int d );
00076   const C& operator()( int i, int j ) { return (*this)[i][j]; };
00077 };
00078 
00079 // IMPLEMENTATION
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 } //namespace mmx
00109 
00110 #endif