realroot_doc 0.1.1
|
00001 /******************************************************************* 00002 * This file is part of the source code of the realroot kernel. 00003 * Author(s): J. Seland SINTEF 00004 * B. Mourrain GALAAD, INRIA 00005 ********************************************************************/ 00006 #ifndef realroot_solver_bspline_hpp 00007 #define realroot_solver_bspline_hpp 00008 /********************************************************************/ 00009 #include <realroot/univariate.hpp> 00010 #include <realroot/polynomial_bernstein.hpp> 00011 #include <realroot/solver.hpp> 00012 //-------------------------------------------------------------------- 00013 #define NO_ROOT -1.0 00014 #define TMPL template<class Real> 00015 namespace mmx { 00016 00017 struct Bspline{}; 00018 00019 //----------------------------------------------------------------------------- 00020 TMPL 00021 Real knotSum(Real* t, int k, int d) 00022 { 00023 Real ret = t[k+1]; 00024 for ( int i=2; i<=d; ++i) ret+=t[k+i]; 00025 return ret; 00026 } 00027 00028 //----------------------------------------------------------------------------- 00029 TMPL 00030 struct solver_bspline { 00031 Real *m_t, *m_c; 00032 unsigned m_n, maxn, m_k ; 00033 int m_d; 00034 Real eps; 00035 00036 solver_bspline(unsigned n, unsigned d, unsigned N=100): m_n(n), maxn(N+n), m_d(d), eps(1e-7) { 00037 m_t= new Real[2*n+N]; 00038 for(unsigned i=0; i< 2*n+N; i++) m_t[i]=Real(1); 00039 m_c = new Real[n+N]; 00040 for(unsigned i=0; i< n+N; i++) m_c[i]=Real(0); 00041 } 00042 00043 int insert_knot ( const Real& x, int mu) ; 00044 Real first_root (); 00045 00046 }; 00047 00048 //----------------------------------------------------------------------------- 00049 // insert knot x in interval mu by Boehms algorithm 00050 // Note: t,c must have capacity at least n+1, n+d+2 respectively 00051 // require that x>=t[mu] 00052 TMPL 00053 int solver_bspline<Real>::insert_knot( const Real& x, int mu) 00054 { 00055 mu = std::max(mu,m_d); 00056 while ( x>=m_t[mu+1]) mu++; 00057 00058 for ( int i=m_n; i>mu; i--) { 00059 m_c[i] = m_c[i-1]; 00060 } 00061 00062 for ( int i=mu; i>=mu-m_d+1; i--) { 00063 const Real alpha = (x-m_t[i])/(m_t[i+m_d]-m_t[i]); 00064 m_c[i] = (1.0-alpha) * m_c[i-1] + alpha * m_c[i]; 00065 } 00066 00067 m_t[m_n+m_d] = 1.0; 00068 00069 for ( int i=m_n; i>mu+1; --i) 00070 m_t[i] = m_t[i-1]; 00071 m_t[mu+1] = x; 00072 00073 // n++; 00074 return mu; 00075 } 00076 00077 // -------------------------------------------------------------------------- 00078 TMPL 00079 Real solver_bspline<Real>::first_root(void) 00080 { 00081 00082 unsigned k = 1; 00083 Real x = NO_ROOT; 00084 00085 for ( ; m_n < maxn; ++m_n ) { 00086 00087 while( k<m_n && (m_c[k-1]*m_c[k] > 0.0) ) 00088 ++k; 00089 00090 00091 // Off end? 00092 if ( k >= m_n ) { 00093 //if (x!= NO_ROOT) 00094 //x = -x; // NO_ROOT; 00095 x = NO_ROOT; 00096 break; 00097 } 00098 00099 // Interval converged? 00100 const Real diff = m_t[k+m_d]-m_t[k]; 00101 00102 if (diff<eps) { 00103 x = m_t[k]; 00104 break; 00105 } 00106 00107 const Real av = knotSum(m_t,k-1, m_d); 00108 const Real lambda = m_c[k-1]/(m_c[k-1]-m_c[k]); 00109 x = (av + lambda*diff)/Real(m_d); 00110 00111 // Stopping criterion 00112 const Real e = std::max(x, m_t[k+m_d-1]) - std::min(x, m_t[k+1] ); 00113 // const Real e = max(fabs(x-t[k+1]),fabs(x-t[k+m_d-1])); 00114 if (e < eps) 00115 break; 00116 00117 // Refine spline 00118 insert_knot(x,k); 00119 } 00120 00121 // dx = d*(m_c[k]-m_c[k-1])/(t[k+m_d]-t[k]); 00122 m_k = k; 00123 return x; 00124 } 00125 //-------------------------------------------------------------------- 00126 template<class Ring> 00127 struct solver<Ring, Bspline> { 00128 typedef double solution_t; 00129 typedef solver_bspline<typename Ring::Scalar> base_t; 00130 00131 template<class POL,class T> static solution_t 00132 first_root(const POL& p, const T& u, const T& v); 00133 00134 template<class POL> static solution_t 00135 first_root(const POL& p); 00136 00137 }; 00138 //-------------------------------------------------------------------- 00142 template<class Ring> 00143 template<class POL, class T> 00144 typename solver<Ring,Bspline>::solution_t 00145 solver<Ring,Bspline>::first_root(const POL& p, 00146 const T& u, const T& v) { 00147 00148 typedef typename Ring::scalar_t Real; 00149 typedef typename POL::Ring ring_t; 00150 typedef typename solver<Ring, Bspline>::base_t base_t; 00151 typedef GMP::rational rational; 00152 00153 rational U,V; 00154 let::assign(U,u); 00155 let::assign(V,v); 00156 int sz= degree(p)+1; 00157 00158 std::vector<rational> bp(sz); 00159 univariate::convertm2b(bp,p,sz,U,V); 00160 00161 solver_bspline<Real> slv(sz,sz-1); 00162 00163 for ( int i = 0; i < sz; i ++ ) { 00164 slv.m_c[i]=as<Real>(bp[i]); 00165 slv.m_t[i]=Real(0); 00166 } 00167 00168 return u +(v-u)*slv.first_root(); 00169 00170 } 00171 00174 template<class Ring> 00175 template<class POL> 00176 typename solver<Ring,Bspline>::solution_t 00177 solver<Ring,Bspline>::first_root(const POL& p) { 00178 00179 typedef typename Ring::Scalar Real; 00180 typedef typename POL::Ring ring_t; 00181 typedef typename solver<Ring, Bspline>::base_t base_t; 00182 typedef GMP::integer integer; 00183 typedef GMP::rational rational; 00184 00185 00186 int d= degree(p), sz=d+1; 00187 solver_bspline<Real> slv(sz,sz-1); 00188 00189 std::vector<rational> bp(sz); 00190 binomials<integer> bn; 00191 rational c; 00192 if(p[0]==0) 00193 return 0; 00194 else if(p[0]<0) { 00195 numerics::rounding<Real> rnd( numerics::rnd_up() ); 00196 for(int i=0;i<sz;i++) { 00197 c= as<rational>(p[i])/bn(d,i); 00198 slv.m_c[i]=as<Real>(c); 00199 } 00200 } else { 00201 numerics::rounding<Real> rnd( numerics::rnd_dw() ); 00202 for(int i=0;i<sz;i++) { 00203 c= as<rational>(p[i])/bn(d,i); 00204 slv.m_c[i]=as<Real>(c); 00205 } 00206 } 00207 for ( int i = 0; i < sz; i ++ ) { 00208 slv.m_t[i]=Real(0); 00209 } 00210 00211 Real x= slv.first_root(); 00212 00213 return x/(1-x); 00214 00215 } 00216 //==================================================================== 00217 } //namespace mmx 00218 #undef TMPL 00219 #undef NO_ROOT 00220 #endif //realroot_solver_bspline_hpp 00221