Developer documentation

system_descartes1d.hpp
Go to the documentation of this file.
1 /********************************************************************
2  * This file is part of the source code of the realroot library.
3  * Author(s): J.P. Pavone, GALAAD, INRIA
4  * $Id: descartes1d.hpp,v 1.1 2005/07/11 10:03:57 jppavone Exp $
5  ********************************************************************/
6 #ifndef realroot_SOLVE_SBDSLV_USOLVER_DESCARTES1D_HPP
7 #define realroot_SOLVE_SBDSLV_USOLVER_DESCARTES1D_HPP
8 //--------------------------------------------------------------------
13 //#include <arithmetix/TypeTests.h>
14 //--------------------------------------------------------------------
15 namespace mmx {
16 //--------------------------------------------------------------------
17 template< typename Prms >
18 struct sign_wanted { typedef texp::false_t result_t; };
19 
20 namespace solvers
21 {
22  /* méthode locales */
23 
24  template<class real_t>
25  struct bsearch /* bissection sous forme monomiale */
26  {
27  real_t * m_data;
28  real_t * m_mons;
29  unsigned m_sz;
30  unsigned m_mxsz;
31 
32  template< class In >
33  /* initialisation: conversion sous forme monomiale */
34  bsearch( const In& bzrep, unsigned sz ) : m_sz(sz)
35  {
36  m_data = new real_t[ 2*sz ];
37  std::copy( bzrep, bzrep + sz, m_data );
38  m_mons = m_data + sz;
39  std::copy( m_data, m_data + sz, m_mons );
41  };
42  ~bsearch() { delete[] m_data; };
43  /* bissection */
44  void reach( real_t * lbzrep, real_t& a, real_t& b, const real_t& eps )
45  {
46  real_t m;
47  if ( lbzrep[m_sz-1] > lbzrep[0] )
48  do
49  if ( upoldse_::horner( m_mons, m_sz, m=(a+b)/2.0 ) < 0 ) a = m; else b = m;
50  while( b-a > eps ) ;
51  else
52  do
53  if ( upoldse_::horner( m_mons, m_sz, m=(a+b)/2.0 ) < 0 ) b = m; else a = m;
54  while( b-a > eps );
55  };
56  };
57 
58  template<class real_t>
59  struct bsearch_castel /* bissection sous forme de Bernstein */
60  {
61  real_t * m_data;
62  unsigned m_sz;
63  template< class In >
64  /* initialisation: copie de la forme de Bernstein */
65  bsearch_castel( const In& bzrep, unsigned sz ) : m_sz(sz)
66  {
67  m_data = new real_t[ sz ];
68  std::copy( bzrep, bzrep + sz, m_data );
69  };
70  ~bsearch_castel() { delete[] m_data; };
71 
72  /* bissection */
73  void reach( real_t * lbzrep, real_t& a, real_t& b, const real_t& eps )
74  {
75  real_t m;
76  if ( lbzrep[m_sz-1] > lbzrep[0] )
77  do
78  if ( brnops::eval( m_data, m_sz, m = (a+b)/2.0 ) < 0 ) a = m; else b = m;
79  while( b-a > eps ) ;
80  else
81  do
82  if ( brnops::eval( m_data, m_sz, m = (a+b)/2.0 ) < 0 ) b = m; else a = m;
83  while( b-a > eps );
84  };
85  };
86 
87  template<class real_t>
88  struct bsearch_newton /* bissection / newton mix */
89  {
90  real_t * m_data;
91  real_t * m_mons;
92  unsigned m_sz;
93  template< class In >
94  /* initialisation conversion sous forme monomiale */
95  bsearch_newton( const In& bzrep, unsigned sz ) : m_sz(sz)
96  {
97  m_data = new real_t[ 2*sz ];
98  std::copy( bzrep, bzrep + sz, m_data );
99  m_mons = m_data + sz;
100  std::copy( m_data, m_data + sz, m_mons );
102  };
103  ~bsearch_newton() { delete[] m_data; };
104 
105  /* bissection / newton mix */
106  void reach( real_t * lbzrep, real_t& a, real_t& b, const real_t& eps )
107  {
108  real_t m;
109  if ( lbzrep[m_sz-1] > lbzrep[0] )
110  do
111  {
112  real_t p,dp,x;
113  /* évaluation du polynôme en m (p) et de sa derivée (dp) */
114  upoldse_::dhorner( p, dp, m_mons, m_sz, m = (a+b)/2.0 );
115  /* étape de bissection */
116  if ( p < 0 ) a = m; else b = m;
117  if ( dp > eps ) /* si la valeur de la derivée n'est pas trop faible */
118  {
119  /* on fait une itération de la méthode de newton */
120  x = m - p/dp;
121  /* si le résultat est dans l'intervalle de la bissection */
122  if ( x > a && x < b )
123  {
124  /* évaluation du polynôme en ce point */
125  real_t xp = upoldse_::horner( m_mons, m_sz, x );
126  /* correction d'une des deux bornes */
127  if ( xp < 0 ) a = x; else b = x;
128  /* recherche de la seconde */
129  if ( xp < 0 )
130  {
131  real_t step = eps;
132  while( xp < 0 && x < b )
133  {
134  x += step;
135  xp = upoldse_::horner( m_mons, m_sz, x );
136  step *= 2;
137  };
138  if ( x < b ) b = x;
139  }
140  else
141  {
142  real_t step = eps;
143  while( xp > 0 && x > a )
144  {
145  x -= step;
146  xp = upoldse_::horner( m_mons, m_sz, x );
147  step *= 2;
148  };
149  if ( x > a ) a = x;
150  };
151  };
152  };
153  }
154  while( b-a > eps );
155  else
156  do
157  {
158  real_t p,dp,x;
159  upoldse_::dhorner( p, dp, m_mons, m_sz, m = (a+b)/2.0 );
160  if ( p < 0 ) b = m; else a = m;
161  if ( dp > eps )
162  {
163  x = m - p/dp;
164  if ( x > a && x < b )
165  {
166  real_t xp = upoldse_::horner( m_mons, m_sz, x );
167  if ( xp < 0 ) b = x; else a = x;
168  if ( xp < 0 )
169  {
170  real_t step = eps/2;
171  while( xp < 0 && x > a )
172  {
173  x -= step;
174  xp = upoldse_::horner( m_mons, m_sz, x );
175  step *= 2;
176  };
177  if ( x > a ) a = x;
178  }
179  else
180  {
181  real_t step = eps/2;
182  while( xp > 0 && x < b )
183  {
184  x += step;
185  xp = upoldse_::horner( m_mons, m_sz, x );
186  step *= 2;
187  };
188  if ( x < b ) b = x;
189  };
190  };
191  };
192  }
193  while( b-a > eps );
194  };
195  };
196 
197  template<class real_t>
199  {
200  real_t * m_data;
201  real_t * m_mons;
202  unsigned m_sz;
203  template< class In >
204  bsearch_newton2( const In& bzrep, unsigned sz ) : m_sz(sz)
205  {
206  m_data = new real_t[ 2*sz ];
207  std::copy( bzrep, bzrep + sz, m_data );
208  m_mons = m_data + sz;
209  std::copy( m_data, m_data + sz, m_mons );
211  };
212  ~bsearch_newton2() { delete[] m_data; };
213 
214  void reach( real_t * lbzrep, real_t& a, real_t& b, const real_t& eps )
215  {
216  real_t m;
217  if ( lbzrep[m_sz-1] > lbzrep[0] )
218  do
219  {
220  // -
221  // -
222  // -----------------
223  // -
224  // -
225  //std::cout << (b-a) << std::endl;
226  real_t p,dp,x;
227  upoldse_::dhorner( p, dp, m_mons, m_sz, m = (a+b)/2.0 );
228  if ( p < 0 ) a = m; else b = m;
229  if ( dp > eps )
230  {
231  real_t ex;
232  int c = 0;
233  x = m;
234  do
235  {
236  ex = x;
237  x = x - p/dp;
238  c ++ ;
239  upoldse_::dhorner(p,dp,m_mons,m_sz,x);
240  }
241  while ( c < 6 );
242  if ( x > a && x < b )
243  {
244  if ( p < 0 )
245  {
246  a = x;
247  p = upoldse_::horner(m_mons,m_sz,x+eps/2);
248  if ( p > 0 ) b = x+eps;
249  }
250  else
251  {
252  b = x;
253  p = upoldse_::horner(m_mons,m_sz,x-eps/2);
254  if ( p < 0 ) a = x-eps/2;
255  };
256  };
257  };
258  }
259  while( b-a > eps );
260  else
261  do
262  {
263  // std::cout << (b-a) << std::endl;
264  real_t p,dp,x;
265  upoldse_::dhorner( p, dp, m_mons, m_sz, m = (a+b)/2.0 );
266  if ( p < 0 ) b = m; else a = m;
267  if ( dp > eps )
268  {
269  real_t ex;
270  int c = 0;
271  x = m;
272  do
273  {
274  ex = x;
275  x = x - p/dp;
276  c ++ ;
277  upoldse_::dhorner(p,dp,m_mons,m_sz,x);
278  }
279  while (c < 6 );
280 
281  if ( x > a && x < b )
282  {
283  if ( p < 0 )
284  {
285  b = x;
286  p = upoldse_::horner(m_mons,m_sz,x-eps/2);
287  if ( p > 0 ) a = x-eps/2;
288  }
289  else
290  {
291  a = x;
292  p = upoldse_::horner(m_mons,m_sz,x+eps/2);
293  if ( p < 0 ) b = x-eps/2;
294  };
295  };
296  }
297  }
298  while( b-a > eps );
299  };
300  };
301 
302  template<class real_t, class local_method = bsearch< real_t > >
304  {
305  public:
306  unsigned m_sz, m_ssz;
307  real_t m_prec;
308  real_t * m_stck;
309  local_method * m_lmth;
310 
311 
312  void reset( unsigned sz, const real_t& prec )
313  {
314  if ( sz <= m_sz && prec >= m_prec )
315  {
316  m_sz = sz;
317  m_prec = prec;
318  return;
319  };
320  m_sz = sz; m_prec = prec;
321  this->alloc();
322  };
323 
324  void split( real_t * r )
325  {
326  real_t * l = r+m_sz+2;
327  brnops::decasteljau(r,l,m_sz);
328  l[m_sz] = r[m_sz];
329  l[m_sz+1] = (r[m_sz]+r[m_sz+1])/2.0;
330  r[m_sz] = l[m_sz+1];
331  };
332  inline real_t precision( real_t * l ) { return l[m_sz+1]-l[m_sz] ; };
333  bool precision_reached( real_t * l ) { return l[m_sz+1]-l[m_sz] < m_prec; };
334 
335  public:
336  /* main loop */
337  /*
338  input : in is a one dimensional vector containing bernstein coefficients (implement an operator[])
339  output: out is a function called on each interval containing roots (assumed to store the results)
340  option: 0 to compute all the roots, n to compute the nth root
341  */
342 
343 
344 
345  void rockwoodcuts( real_t * nxt, real_t * prv, real_t * mid )
346  {
347  // [-------------] b
348  // [---][--------] b
349  // [---][---][---] b
350  real_t i0, i1;
351  brnops::rockwood_cut( i0, nxt, m_sz );
352  brnops::rockwood_cut( i1, nxt+m_sz-1, m_sz, -1 );
353  std::cout << i0 << ", " << (1.0-i1) << std::endl;
354  i1 = (1.0-i1);
355  brnops::decasteljau(nxt,prv,m_sz,i0);
356  brnops::decasteljau(nxt,mid,m_sz,(i1-i0)/(1.0-i0));
357  i0 = (1.0-i0)*nxt[m_sz] + i0*nxt[m_sz+1];
358  i1 = (1.0-i1)*nxt[m_sz] + i1*nxt[m_sz+1];
359  prv[m_sz] = nxt[m_sz];
360  prv[m_sz+1] = i0;
361  mid[m_sz] = i0;
362  mid[m_sz+1] = i1;
363  nxt[m_sz] = i1;
364  };
365 
366  inline void set_sz( unsigned sz ) { m_sz = sz;};
367 
368  template< class Prms > inline
369  void output( Prms& prms, real_t * stck, const texp::true_t& )
370  { prms.output( stck[m_sz], stck[m_sz+1], stck[0] > 0, stck[m_sz-1] > 0 ); };
371  template< class Prms > inline
372  void output( Prms& prms, real_t * stck, const texp::false_t& )
373  { prms.output( stck[m_sz], stck[m_sz+1] ); };
374 
375  template< class Prms > inline
376  void output( Prms& prms, real_t * stck )
377  { output( prms, stck, sign_wanted< Prms >::result_t() ); };
378 
379  template<class Prms,class In>
380  unsigned solve( Prms& prms, const In& in, int option = 0 )
381  {
382  for ( unsigned i = 0; i < m_sz; i ++ ) m_stck[i] = in[i];
383  m_stck[m_sz] = 0.0; m_stck[m_sz+1] = 1.0;
384  unsigned roots = 0;
385  const unsigned inc = m_sz+2;
386  real_t * stck = m_stck;
387  real_t * stop = stck-inc;
388  do
389  {
390  unsigned sgn = vctops::sgncnt(stck,m_sz);
391  switch( sgn )
392  {
393  case 0:
394  stck -= inc;
395  break;
396  case 1:
397  roots ++;
398  if ( !option || (roots == option) )
399  {
400  if ( m_lmth == 0 ) m_lmth = new local_method(in,m_sz);
401  m_lmth->reach( stck, stck[m_sz], stck[m_sz+1], m_prec );
402  output( prms, stck );
403  };
404  stck -= inc;
405  break;
406  default:
407  if( precision( stck ) < m_prec )
408  {
409  roots++;
410  if ( !option || (roots == option) ) output(prms,stck);
411  stck -= inc;
412  break;
413  };
414  split(stck);
415  stck += inc;
416  break;
417  }
418  }
419  while( stck != stop );
420  if ( m_lmth ) { delete m_lmth; m_lmth = 0; };
421  return roots;
422  };
423 
424 
425 
426  descartes_solver( unsigned sz, const real_t& eps = 1e-12 )
427  {
428  m_stck = 0;
429  m_sz = sz;
430  m_prec = eps;
431  m_lmth = 0;
432  unsigned maxdeep = 1;
433  real_t ex = 1;
434  while ( ex > m_prec ) { ex/=2; maxdeep ++ ; };
435  // std::cout << maxdeep << std::endl;
436  maxdeep ++;
437  maxdeep *= 3;
438  unsigned tsz = maxdeep*(2+m_sz);
439  m_stck = new real_t[ tsz ];
440  };
441 
443  delete[] m_stck;
444  };
445  };
446 };
447 //--------------------------------------------------------------------
448 } //namespace mmx
449 /********************************************************************/
450 #endif //
bsearch_newton(const In &bzrep, unsigned sz)
Definition: system_descartes1d.hpp:95
void output(Prms &prms, real_t *stck)
Definition: system_descartes1d.hpp:376
real_t * m_mons
Definition: system_descartes1d.hpp:28
const C & b
Definition: Interval_glue.hpp:25
real_t eval(real_t const *const src, unsigned sz, const real_t &t, int st=1)
Definition: loops_brnops.hpp:47
bsearch(const In &bzrep, unsigned sz)
Definition: system_descartes1d.hpp:34
void output(Prms &prms, real_t *stck, const texp::true_t &)
Definition: system_descartes1d.hpp:369
unsigned sgncnt(real_t const *b, unsigned sz, int st=1)
Definition: loops_vctops.hpp:144
unsigned m_sz
Definition: system_descartes1d.hpp:62
void decasteljau(real_t *r, unsigned sz, const real_t &t, int str=1)
Definition: loops_brnops.hpp:23
void reach(real_t *lbzrep, real_t &a, real_t &b, const real_t &eps)
Definition: system_descartes1d.hpp:44
void reach(real_t *lbzrep, real_t &a, real_t &b, const real_t &eps)
Definition: system_descartes1d.hpp:73
real_t * m_data
Definition: system_descartes1d.hpp:90
real_t * m_data
Definition: system_descartes1d.hpp:200
Definition: system_descartes1d.hpp:88
unsigned m_sz
Definition: system_descartes1d.hpp:202
~bsearch()
Definition: system_descartes1d.hpp:42
unsigned m_sz
Definition: system_descartes1d.hpp:92
Definition: system_descartes1d.hpp:198
unsigned m_sz
Definition: system_descartes1d.hpp:306
real_t * m_mons
Definition: system_descartes1d.hpp:201
bsearch_newton2(const In &bzrep, unsigned sz)
Definition: system_descartes1d.hpp:204
unsigned m_sz
Definition: system_descartes1d.hpp:29
~bsearch_castel()
Definition: system_descartes1d.hpp:70
real_t * m_data
Definition: system_descartes1d.hpp:61
Definition: system_descartes1d.hpp:18
structure defining a positive answer
Definition: texp_bool.hpp:7
unsigned solve(Prms &prms, const In &in, int option=0)
Definition: system_descartes1d.hpp:380
TMPL void copy(Polynomial &r, const Polynomial &a)
Copy of a in r.
Definition: sparse_monomials.hpp:613
bool in(const T &x, const Interval< T, r > &y)
Definition: Interval_fcts.hpp:100
real_t * m_mons
Definition: system_descartes1d.hpp:91
int sgn(FT a)
Sign of a.
Definition: solver_mv_monomial_tests.hpp:416
Definition: system_descartes1d.hpp:25
void toMonoms(T *bzc, size_t sz, int st=1)
Definition: bernstein_bzenv.hpp:64
void reach(real_t *lbzrep, real_t &a, real_t &b, const real_t &eps)
Definition: system_descartes1d.hpp:214
~descartes_solver()
Definition: system_descartes1d.hpp:442
~bsearch_newton()
Definition: system_descartes1d.hpp:103
unsigned m_mxsz
Definition: system_descartes1d.hpp:30
real_t * m_stck
Definition: system_descartes1d.hpp:308
real_t precision(real_t *l)
Definition: system_descartes1d.hpp:332
void split(real_t *r)
Definition: system_descartes1d.hpp:324
void reset(unsigned sz, const real_t &prec)
Definition: system_descartes1d.hpp:312
Definition: system_descartes1d.hpp:59
~bsearch_newton2()
Definition: system_descartes1d.hpp:212
void reach(real_t *lbzrep, real_t &a, real_t &b, const real_t &eps)
Definition: system_descartes1d.hpp:106
void rockwoodcuts(real_t *nxt, real_t *prv, real_t *mid)
Definition: system_descartes1d.hpp:345
descartes_solver(unsigned sz, const real_t &eps=1e-12)
Definition: system_descartes1d.hpp:426
const C & c
Definition: Interval_glue.hpp:45
real_t m_prec
Definition: system_descartes1d.hpp:307
void output(Prms &prms, real_t *stck, const texp::false_t &)
Definition: system_descartes1d.hpp:372
structure defining a negative answer
Definition: texp_bool.hpp:9
texp::false_t result_t
Definition: system_descartes1d.hpp:18
Definition: bernstein_bzenv.hpp:17
bool precision_reached(real_t *l)
Definition: system_descartes1d.hpp:333
bsearch_castel(const In &bzrep, unsigned sz)
Definition: system_descartes1d.hpp:65
Definition: array.hpp:12
void set_sz(unsigned sz)
Definition: system_descartes1d.hpp:366
Definition: system_descartes1d.hpp:303
real_t * m_data
Definition: system_descartes1d.hpp:27
unsigned m_ssz
Definition: system_descartes1d.hpp:306
void horner(parm_t &res, coeff_t const *const mnms, unsigned sz, const parm_t &t, int st=1)
Definition: loops_upoldse.hpp:19
void dhorner(real_t &p, real_t &dp, real_t const *const mnms, unsigned sz, const real_t &t)
Definition: loops_upoldse.hpp:33
bool rockwood_cut(real_t &t, real_t const *b, unsigned sz, int st=1)
Definition: loops_brnops.hpp:155
local_method * m_lmth
Definition: system_descartes1d.hpp:309
Home