OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
Equation.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // "Copyright Centre National d'Etudes Spatiales"
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 //----------------------------------------------------------------------------
10 // $Id$
11 
12 #include <otb/Equation.h>
13 
14 namespace ossimplugins
15 {
16 
17 
18 const double Equation::Epsilon = 1.e-12;
19 
21  _coefficients(NULL),
22  _degree(0),
23  _nbrSol(0),
24  _solutions(NULL)
25 {
26  _order.clear();
27 }
28 
30 {
31  if (_coefficients != NULL)
32  delete [] _coefficients;
33  if(_solutions != NULL)
34  delete [] _solutions;
35 }
36 
37 Equation::Equation(int degree, std::complex<double>* coefficients):
38  _coefficients(NULL),
39  _degree(0),
40  _nbrSol(0),
41  _solutions(NULL)
42 {
43  _order.clear();
44  CreateEquation(degree, coefficients);
45 }
46 
47 void Equation::CreateEquation(int degree, std::complex<double>* coefficients)
48 {
49  if (_coefficients != NULL)
50  {
51  delete [] _coefficients;
52  }
53 
54  if(_order.size() != 0)
55  _order.clear();
56  if(_solutions != NULL)
57  delete [] _solutions;
58 
59  _coefficients = new std::complex<double>[degree+1];
60  _degree = degree;
61 
62  for (int i=0;i<=degree;i++)
63  {
64  _coefficients[i] = coefficients[i];
65  }
66 }
67 
69 {
71 }
72 
74 {
76  return *this;
77 }
78 
80 {
81  double r = 0.0;
82  _trueDegree = _degree +1;
83  while (r <= Epsilon && _trueDegree > 0)
84  {
85  _trueDegree = _trueDegree - 1 ;
87  }
88 }
89 
91 {
92  for (int i=0;i<_trueDegree;i++)
93  {
95  }
96  _coefficients[_trueDegree] = std::complex<double>(1.0,0.0);
97 
98  int eMax = 0;
99  int eMin = 0;
100  int e;
101  double r;
102 
103  /*
104  * Normalisation by a power of 10
105  */
106  for (int i = 0 ; i < _trueDegree ; i++)
107  {
108  float rr = abs(_coefficients[i]) ;
109  if (rr >= Epsilon)
110  {
111  rr = log10(rr) ;
112  e = ((int)rr) / ((int)(_trueDegree - i)) ;
113  if (e > eMax)
114  eMax = e ;
115  if (e < eMin)
116  eMin = e ;
117  }
118  }
119 
120  /*
121  * Normalisation for big values
122  */
123  if (eMax > 0)
124  {
125  /* Normalisation of the unknown for big values */
127  _normalisationCoefficient = pow (10.0, (double)eMax) ;
128  r = 1.0 ;
129  for (int i = _trueDegree-1 ; i >= 0 ; i--)
130  {
131  r = r * _normalisationCoefficient ;
132  _coefficients[i] = _coefficients[i] / std::complex<double>(r,0.0);
133  }
134  }
135  else if (eMin < 0)
136  {
137  /* Normalisation of the unknown for small */
139  _normalisationCoefficient = pow(10.0,(double)(-eMin)) ;
140  r = 1.0 ;
141  for (int i = _trueDegree-1 ; i >= 0 ; i--)
142  {
143  r = r * _normalisationCoefficient ;
144  _coefficients[i] = _coefficients[i] * std::complex<double>(r,0.0);
145  }
146  }
147 }
148 
150 {
152  {
153  for (int i=0;i<_nbrSol;i++)
154  {
155  _solutions[i] = _solutions[i] * std::complex<double>(_normalisationCoefficient,0.0);
156  }
157  }
158  else
159  {
160  for (int i=0;i<_nbrSol;i++)
161  {
162  _solutions[i] = _solutions[i] / std::complex<double>(_normalisationCoefficient,0.0);
163  }
164  }
165 }
166 std::complex<double> Equation::Proche(std::complex<double> z, double epsilon)
167 {
168  double x, y, ax, ay ;
169  std::complex<double> result ;
170 
171  x = z.real();
172  y = z.imag();
173  ax = fabs(x);
174  ay = fabs(y);
175 
176  if (ax < epsilon && ay < epsilon)
177  result = std::complex<double>(0.0, 0.0) ;
178  else if (ay < epsilon)
179  result = std::complex<double>(x, 0.0) ;
180  else if (ax < epsilon)
181  result = std::complex<double>(0.0, y) ;
182  else
183  {
184  if ((ay / ax) < epsilon)
185  result = std::complex<double>(x, 0.0) ;
186  else if ((ax / ay) < epsilon)
187  result = std::complex<double>(0.0,y) ;
188  else
189  result = z ;
190  }
191 
192  return result ;
193 }
194 
196 {
198  Normalisation();
199 
200  if(_trueDegree == 1)
201  {
202  Solve1();
203  }
204  else if(_trueDegree == 2)
205  {
206  Solve2();
207  }
208  else if(_trueDegree == 3)
209  {
210  Solve3();
211  }
212  else if(_trueDegree == 4)
213  {
214  Solve4();
215  }
216  DeNormalisation();
217 }
218 
220 {
221  _nbrSol = 1;
222 
223  if(_order.size() != 0)
224  _order.clear();
225 
226  _order.push_back(1);
227 
228  if(_solutions != NULL)
229  delete [] _solutions;
230  _solutions = new std::complex<double>[1];
232 }
233 
235 {
236  double r1, r2 ;
237  // double epsilon = 1.e-12 ;
238  std::complex<double> t1, t2, d, z ;
239  std::complex<double> aa[2] ;
240 
241  aa[0] = _coefficients[0]/ _coefficients[2];
242  aa[1] = _coefficients[1]/ _coefficients[2];
243 
244  t1 = aa[1]* aa[1] ;
245  t2 = aa[0]* std::complex<double>(4.0, 0.0) ;
246  r1 = abs(t1) ;
247  r2 = abs(t2) ;
248  if (r2 > r1)
249  r1 = r2 ;
250  if (r1 > Epsilon)
251  {
252  d = t1- t2 ;
253  t1 = d/std::complex<double>(r1, 0.0) ;
254  }
255  else
256  {
257  d = std::complex<double>(0.0, 0.0) ;
258  t1 = std::complex<double>(0.0, 0.0) ;
259  }
260  r1 = abs (t1) ;
261 
262  if (r1 <= Epsilon)
263  {
264  /* 1 double root */
265 
266  if(_solutions != NULL)
267  delete [] _solutions;
268  _solutions = new std::complex<double>[1];
269 
270  if(_order.size() != 0)
271  _order.clear();
272 
273  _nbrSol = 1 ;
274  z = aa[1]/std::complex<double>(-2.0, 0.0);
275  _solutions[0] = Proche (z, Epsilon) ;
276  _order.push_back(2);
277  }
278  else
279  {
280  /* 2 simple roots */
281 
282  if(_solutions != NULL)
283  delete [] _solutions;
284  _solutions = new std::complex<double>[2];
285 
286  if(_order.size() != 0)
287  _order.clear();
288 
289  _nbrSol = 2 ;
290  d = sqrt(d) ;
291  z = (d-aa[1])/std::complex<double>(2.0, 0.0) ;
292  _solutions[0] = Proche (z, Epsilon) ;
293  z = (d+aa[1])/std::complex<double>(-2.0, 0.0);
294  _solutions[1] = Proche (z, Epsilon) ;
295  _order.push_back(1);
296  _order.push_back(1);
297  }
298 }
299 
300 void Equation::Solve3(int d4)
301 {
302  int d3_1r3 , d3_1r2_1r1 ;
303  double r1, r2, ra[3] ;
304  // double epsilon = 1.e-12 ;
305  std::complex<double> j, j2 ;
306  std::complex<double> d, q, r, s, t, u, v, w ;
307  std::complex<double> aa[3], zProv[3][3] ;
308 
309 
310  j = std::complex<double>(-0.5, sqrt (3.0) / 2.0) ;
311  j2 = std::complex<double>(-0.5, -sqrt (3.0) / 2.0) ;
312 
313  /* Normalisation of coefficients */
314  for (int i1 = 0; i1 < 3; i1++)
315  aa[i1] = _coefficients[i1]/_coefficients[3];
316 
317  if ( d4 == 0 )
318  {
319  /* Test of existence of a triple root */
320  d3_1r3 = TestDegree3Triple(aa, Epsilon) ;
321 
322  /* Test of existence of 1 doubleroot + 1 simple root */
323  d3_1r2_1r1 = TestDegree3SimpleDouble(aa, Epsilon) ;
324  }
325  else
326  {
327  d3_1r3 = 0 ;
328  d3_1r2_1r1 = 0 ;
329  }
330 
331 
332  if (d3_1r3 == 1)
333  {
334  /* 1 triple root */
335  if(_solutions != NULL)
336  delete [] _solutions;
337  _solutions = new std::complex<double>[1];
338 
339  if(_order.size() != 0)
340  _order.clear();
341 
342  _nbrSol = 1 ;
343  _solutions[0] = Proche (aa[2]/std::complex<double>(-3.0, 0.0) , Epsilon) ;
344  _order.push_back(3);
345  }
346  else if (d3_1r2_1r1 == 1)
347  {
348  /* 1 simple root + 1 double root */
349 
350  if(_solutions != NULL)
351  delete [] _solutions;
352  _solutions = new std::complex<double>[2];
353 
354  if(_order.size() != 0)
355  _order.clear();
356 
357  u = (aa[1]* aa[2])/ std::complex<double>(6.0, 0.0) ;
358  v = aa[0]/ std::complex<double> (2.0, 0.0);
359  w = pow(aa[2], 3.0)/ std::complex<double>(27.0, 0.0);
360  r = (u-v)- w ;
361  u = pow (r, 1.0 / 3.0) ;
362  w = aa[2]/ std::complex<double>(3.0, 0.0);
363  zProv[0][0] = -u;
364  zProv[0][1] = u * std::complex<double>(2.0,0.0);
365  zProv[1][0] = u * (j + std::complex<double>(1.0, 0.0));
366  zProv[1][1] = u * (j2* std::complex<double>(2.0, 0.0));
367  zProv[2][0] = u * (j2+ std::complex<double>(1.0, 0.0));
368  zProv[2][1] = u * (j * std::complex<double>(2.0, 0.0));
369  for (int i1 = 0; i1 <= 2; i1++)
370  {
371  zProv[i1][0] = zProv[i1][0]- w;
372  zProv[i1][1] = zProv[i1][1]- w;
373  }
374  for (int i2 = 0; i2 < 3; i2++)
375  {
376  u = std::complex<double>(1.0, 0.0) ;
377 
378  for (int i1 = 2; i1 >= 0; i1--)
379  u = u*zProv[i2][0]+aa[i1] ;
380 
381  r1 = abs (u) ;
382  u = std::complex<double>(1.0, 0.0) ;
383 
384  for (int i1 = 2; i1 >= 0; i1--)
385  u = u*zProv[i2][1]+ aa[i1] ;
386 
387  r2 = abs (u) ;
388  ra[i2] = r1 * r1 + r2 * r2 ;
389  }
390  int i3 = IndiceMin(3, ra) ;
391  _solutions[0] = Proche ( zProv[i3][0] , Epsilon ) ;
392  _solutions[1] = Proche ( zProv[i3][1] , Epsilon ) ;
393  _nbrSol = 2 ;
394  _order.push_back(2);
395  _order.push_back(1);
396  }
397  else
398  {
399  /* 3 simple roots */
400  u = aa[1]/ std::complex<double>(3.0, 0.0);
401  v = (aa[2]* aa[2]) / std::complex<double>(9.0, 0.0) ;
402  q = u- v ;
403  u = (aa[1]* aa[2]) / std::complex<double>(6.0, 0.0) ;
404  v = aa[0]/ std::complex<double>(2.0, 0.0) ;
405  w = pow(aa[2], 3.0) / std::complex<double>(27.0, 0.0);
406  r = (u-v) - w ;
407  d = sqrt(pow(q, 3.0) + pow(r, 2.0)) ;
408  s = pow ((r + d) , 1.0 / 3.0) ;
409  t = pow ((r - d) , 1.0 / 3.0) ;
410  w = aa[2]/ std::complex<double>(3.0, 0.0);
411 
412  zProv[0][0] = s+ t;
413  zProv[0][1] = (j* s) + (j2* t) ;
414  zProv[0][2] = (j2* s) + (j* t) ;
415  zProv[1][0] = s + (j* t);
416  zProv[1][1] = (j* s) + t;
417  zProv[1][2] = j2 * (s+ t) ;
418  zProv[2][0] = s + (j2* t) ;
419  zProv[2][1] = j * (s+ t);
420  zProv[2][2] = (j2* s) + t;
421  for (int i1 = 0; i1 < 3; i1++)
422  {
423  for (int i2 = 0; i2 < 3; i2++)
424  zProv[i1][i2] = zProv[i1][i2]- w;
425  }
426  for (int i3 = 0; i3 < 3; i3++)
427  {
428  ra[i3] = 0.0 ;
429  for (int i2 = 0; i2 < 3; i2++)
430  {
431  u = std::complex<double>(1.0, 0.0) ;
432  for (int i1 = 2; i1 >= 0; i1--)
433  u = (u* zProv[i3][i2]) + aa[i1] ;
434 
435  r1 = abs (u) ;
436  ra[i3] = ra[i3] + r1 * r1 ;
437  }
438  }
439  int i1 = IndiceMin(3, ra) ;
440 
441 
442  if(_solutions != NULL)
443  delete [] _solutions;
444  _solutions = new std::complex<double>[3];
445 
446  if(_order.size() != 0)
447  _order.clear();
448 
449  _nbrSol = 3 ;
450  for (int i3 = 0; i3 < 3; i3++)
451  _solutions[i3] = Proche (zProv[i1][i3] , Epsilon) ;
452  _order.push_back(1);
453  _order.push_back(1);
454  _order.push_back(1);
455  }
456 }
457 
459 {
460  int d4_1r4, d4_2r2, d4_1r3_1r1, d4_1r2_2r1 ;
461  int d4 = 1 ;
462  double epsilon = 1.e-12 ;
463  double r, h[4] ;
464  std::complex<double> d, u, v, w, x, y ;
465  std::complex<double> aa[4], k[4], b[4], zProv[2][4] ;
466 
467 
468  /* Normalisation of coefficients */
469  for (int i1 = 0; i1 < 4; i1++)
470  aa[i1] = _coefficients[i1]/ _coefficients[4];
471 
472  /* Equation reduction : on the form */
473  /* (x-s)**4 + p(x-s)**2 + q(x-s) + r = 0 */
474  /* these coefficients are inserted into table k : */
475  /* k[0] = s */
476  /* k[1] = p */
477  /* k[2] = q */
478  /* k[3] = r */
479  k[0] = aa[3]/ std::complex<double>(-4.0, 0.0) ;
480  u = aa[2] ;
481  v = ((aa[3]* std::complex<double>(3.0, 0.0)) * (aa[3]/ std::complex<double>(8.0, 0.0))) ;
482  h[0] = abs (u) ;
483  h[1] = abs (v) ;
484 
485  if (h[0] < h[1])
486  h[0] = h[1] ;
487  if (h[0] > Epsilon)
488  k[1] = u- v;
489  else
490  k[1] = std::complex<double>(0.0, 0.0) ;
491 
492  u = aa[1] ;
493  v = (aa[2]* aa[3]) / std::complex<double>(2.0, 0.0) ;
494  w = pow (aa[3], 3.0) / std::complex<double>(8.0, 0.0) ;
495  h[0] = abs (u) ;
496  h[1] = abs (v) ;
497  h[2] = abs (w) ;
498  h[0] = h[IndiceMax(3, h)] ;
499  if (h[0] > Epsilon)
500  k[2] = (u- v)+ w ;
501  else
502  k[2] = std::complex<double>(0.0, 0.0) ;
503  u = aa[0] ;
504  v = (aa[1]* aa[3]) / std::complex<double>(4.0, 0.0);
505  w = (aa[2]* aa[3]) * (aa[3]/ std::complex<double>(16.0, 0.0)) ;
506  x = pow (aa[3], 4.0) * std::complex<double>(3.0 / 256.0, 0.0) ;
507  h[0] = abs (u) ;
508  h[1] = abs (v) ;
509  h[2] = abs (w) ;
510  h[3] = abs (x) ;
511  h[0] = h[IndiceMax(4, h)] ;
512 
513  if (h[0]>Epsilon)
514  k[3] = (u- v) + (w- x) ;
515  else
516  k[3] = std::complex<double>(0.0, 0.0) ;
517 
518  /* Test of existence of a quadruple root */
519  d4_1r4 = TestDegree4Quad (k, epsilon) ;
520 
521  /* Test of existence of 2 double roots */
522  d4_2r2 = TestDegree4DoubleDouble (aa, k, epsilon) ;
523 
524  /* Test of existence of 1 triple root + 1 simple root */
525  d4_1r3_1r1 = TestDegree4SimpleTriple (aa, k, epsilon) ;
526 
527  /* Test of existence of 1 double root + 2 simple roots */
528  d4_1r2_2r1 = TestDegreeSimpleSimpleDouble (k, epsilon) ;
529 
530 
531  if (d4_1r4 == 1)
532  {
533  /* 1 quadruple root */
534 
535  if(_solutions != NULL)
536  delete [] _solutions;
537  _solutions = new std::complex<double>[1];
538 
539 
540  if(_order.size() != 0)
541  _order.clear();
542 
543  _nbrSol = 1 ;
544  _solutions[0] = Proche (k[0], Epsilon) ;
545  _order.push_back(4);
546  }
547  else if (d4_2r2 == 1)
548  {
549  /* 2 double roots */
550 
551  if(_solutions != NULL)
552  delete [] _solutions;
553  _solutions = new std::complex<double>[2];
554 
555  if(_order.size() != 0)
556  _order.clear();
557 
558  u = sqrt (k[1]/ std::complex<double>(-2.0, 0.0)) ;
559  _solutions[0] = Proche ((k[0]+ u) , Epsilon) ;
560  _solutions[1] = Proche ((k[0]- u) , Epsilon) ;
561  _nbrSol = 2 ;
562  _order.push_back(2);
563  _order.push_back(2);
564  }
565  else if (d4_1r3_1r1 == 1)
566  {
567  /* 1 triple root + 1 simple root */
568 
569  if(_solutions != NULL)
570  delete [] _solutions;
571  _solutions = new std::complex<double>[2];
572 
573  if(_order.size() != 0)
574  _order.clear();
575 
576  u = (k[2]* std::complex<double>(-3.0, 0.0)) / (k[1]* std::complex<double>(4.0, 0.0)) ;
577  v = u * std::complex<double>(-3.0, 0.0);
578  _solutions[0] = Proche ((k[0]+ u) , Epsilon) ;
579  _solutions[1] = Proche ((k[0]+ v) , Epsilon) ;
580  _nbrSol = 2 ;
581  _order.push_back(3);
582  _order.push_back(1);
583  }
584  else if (d4_1r2_2r1 == 1)
585  {
586  /* 1 double root + 2 simple roots */
587 
588  if(_solutions != NULL)
589  delete [] _solutions;
590  _solutions = new std::complex<double>[3];
591 
592  if(_order.size() != 0)
593  _order.clear();
594 
595  if (abs (k[1]) <= Epsilon)
596  {
597  u = (k[3]* std::complex<double>(-4.0, 0.0)) / (k[2]* std::complex<double>(3.0, 0.0));
598  v = sqrt ((u* std::complex<double>(-2.0, 0.0)) * u) ;
599  _solutions[0] = Proche ((k[0]+ u) , Epsilon) ;
600  _solutions[1] = Proche ((k[0] + (v- u)) , Epsilon) ;
601  _solutions[2] = Proche ((k[0] - (v+ u)) , Epsilon) ;
602  }
603  else
604  {
605  v = (k[2]* k[2]) * std::complex<double>(9.0, 0.0) ;
606  w = (k[1]* k[3]) * std::complex<double>(32.0, 0.0) ;
607  u = sqrt((v- w)) ;
608  v = (k[2] * std::complex<double>(-3.0, 0.0)) ;
609  w = (k[1] * std::complex<double>(4.0, 0.0)) ;
610  x = ((v+ u) / w) ;
611  y = ((v- u) / w) ;
612  u = ((x* x) * std::complex<double>(-2.0, 0.0)) ;
613  u = sqrt((u- k[1])) ;
614  v = ((y* y) * std::complex<double>(-2.0, 0.0)) ;
615  v = sqrt((v- k[1])) ;
616  zProv[0][0] = (k[0]+ x) ;
617  zProv[0][1] = (k[0] - (x- u)) ;
618  zProv[0][2] = (k[0] - (x+ u)) ;
619  zProv[1][0] = (k[0]+ y) ;
620  zProv[1][1] = (k[0] - (y- v)) ;
621  zProv[1][2] = (k[0] - (y+ v)) ;
622  h[0] = 0.0 ;
623  h[1] = 0.0 ;
624  for (int i1 = 0; i1 < 3; i1++)
625  {
626  u = std::complex<double>(1.0, 0.0) ;
627  for (int i2 = 3; i2 >= 0; i2--)
628  u = ((u* zProv[0][i1])+ aa[i2]) ;
629 
630  r = abs (u) ;
631  h[0] = h[0] + r * r ;
632  u = std::complex<double>(1.0, 0.0) ;
633  for (int i2 = 3; i2 >= 0; i2--)
634  u = ((u* zProv[1][i1])+ aa[i2]) ;
635  r = abs (u) ;
636  h[1] = h[1] + r * r ;
637  }
638  int i1 = IndiceMin (2, h) ;
639  for (int i2 = 0; i2 < 3; i2++)
640  _solutions[i2] = Proche (zProv[i1][i2] , Epsilon) ;
641  }
642  _nbrSol = 3 ;
643  _order.push_back(2);
644  _order.push_back(1);
645  _order.push_back(1);
646  }
647  else
648  {
649  /* 4 simple roots */
650  u = ((aa[0]* aa[2]) * std::complex<double>(4.0, 0.0)) ;
651  v = (aa[1] * aa[1]) ;
652  w = ((aa[0]* aa[3]) * aa[3]) ;
653  b[0] = (u - (v+ w)) ;
654  b[1] = ((aa[1]* aa[3]) - (aa[0]* std::complex<double>(4.0, 0.0))) ;
655  b[2] = -aa[2] ;
656  b[3] = std::complex<double>(1.0, 0.0) ;
657 
658  /* The third degree equation is solved by forcing 3 distinct roots (computation precision problem) */
659  Equation eq(3,b);
660  eq.Solve3(d4);
661 
662  //Solve3(d4);
663  h[0] = abs ((eq.get_solutions()[1]- eq.get_solutions()[2])) ; /* the root the most distant to */
664  h[1] = abs ((eq.get_solutions()[0]- eq.get_solutions()[2])) ; /* the 2 others is selected */
665  h[2] = abs ((eq.get_solutions()[0]- eq.get_solutions()[1])) ;
666  int i1 = IndiceMin (3, h) ;
667  u = eq.get_solutions()[i1] ;
668  v = ((aa[2]- u) * std::complex<double>(4.0, 0.0)) ;
669  v = sqrt(((aa[3]* aa[3]) - v)) ;
670  w = sqrt(((u* u) - (aa[0]* std::complex<double>(4.0, 0.0)))) ;
671  x = ((aa[3]+ v) / std::complex<double>(2.0, 0.0)) ;
672  y = ((u+ w) / std::complex<double>(2.0, 0.0)) ;
673  d = sqrt(((x* x) - (y* std::complex<double>(4.0, 0.0)))) ;
674  zProv[0][0] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
675  zProv[0][1] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
676 
677  x = ((aa[3]- v) / std::complex<double>(2.0, 0.0)) ;
678  y = ((u- w) / std::complex<double>(2.0, 0.0)) ;
679  d = sqrt((x*x) - (y* std::complex<double>(4.0, 0.0))) ;
680  zProv[0][2] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
681  zProv[0][3] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
682 
683  x = ((aa[3]+ v) / std::complex<double>(2.0, 0.0)) ;
684  y = ((u- w) / std::complex<double>(2.0, 0.0)) ;
685  d = sqrt(((x*x) - (y* std::complex<double>(4.0, 0.0)))) ;
686  zProv[1][0] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
687  zProv[1][1] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
688 
689  x = ((aa[3]- v) / std::complex<double>(2.0, 0.0)) ;
690  y = ((u+ w) / std::complex<double>(2.0, 0.0)) ;
691  d = sqrt((x*x) - (y* std::complex<double>(4.0, 0.0))) ;
692  zProv[1][2] = ((x- d) / std::complex<double>(-2.0, 0.0)) ;
693  zProv[1][3] = ((x+ d) / std::complex<double>(-2.0, 0.0)) ;
694 
695  h[0] = 0.0 ;
696  h[1] = 0.0 ;
697  for (int i1 = 0; i1 < 4; i1++)
698  {
699  u = std::complex<double>(1.0, 0.0) ;
700 
701  for (int i2 = 3; i2 >= 0; i2--)
702  u = ((u* zProv[0][i1])+ aa[i2]) ;
703 
704  r = abs (u) ;
705  h[0] = h[0] + r * r ;
706  u = std::complex<double>(1.0, 0.0) ;
707 
708  for (int i2 = 3; i2 >= 0; i2--)
709  u = ((u* zProv[1][i1])+ aa[i2]) ;
710 
711  r = abs(u) ;
712  h[1] = h[1] + r * r ;
713  }
714  i1 = IndiceMin (2, h) ;
715 
716  if(_solutions != NULL)
717  delete [] _solutions;
718  _solutions = new std::complex<double>[4];
719 
720  if(_order.size() != 0)
721  _order.clear();
722 
723  for (int i2 = 0; i2 < 4; i2++)
724  {
725  _solutions[i2] = Proche (zProv[i1][i2] , Epsilon) ;
726  _order.push_back(1);
727  }
728  _nbrSol = 4 ;
729  }
730 
731 }
732 
733 int Equation::TestDegree3Triple(std::complex<double>* a, double epsilon)
734 {
735  double d, dp[2], q, r ;
736  std::complex<double> u, v ;
737 
738 
739  u = a[2]* a[2] ;
740  v = a[1]*std::complex<double>(3.0, 0.0) ;
741  dp[0] = abs (u) ;
742  dp[1] = abs (v) ;
743  d = (dp[0] > dp[1]) ? dp[0] : dp[1] ;
744  q = (d > epsilon) ? abs((u- v)/ std::complex<double> (d, 0.0))
745  : 0.0 ;
746 
747  u = a[1]* a[2];
748  v = a[0]* std::complex<double>(9.0, 0.0) ;
749  dp[0] = abs (u) ;
750  dp[1] = abs (v) ;
751  d = (dp[0] > dp[1]) ? dp[0] : dp[1] ;
752  r = (d > epsilon) ? abs ((u-v)/std::complex<double>(d, 0.0))
753  : 0.0 ;
754 
755  return ((q <= epsilon) && (r <= epsilon)) ? 1 : 0 ;
756 }
757 
758 int Equation::TestDegree3SimpleDouble(std::complex<double>* a, double epsilon)
759 {
760  double d, k, r[5] ;
761  std::complex<double> u, t[5] ;
762 
763 
764  u = a[1]*a[2] ;
765  t[0] = pow (a[1], 3.0)*std::complex<double>(4.0, 0.0) ;
766  t[1] = a[0]*a[0]* std::complex<double>(27.0, 0.0);
767  t[2] = a[0]* std::complex<double>(4.0, 0.0)*pow (a[2], 3.0) ;
768  t[3] = -(u* u) ;
769  t[4] = std::complex<double>(-18.0, 0.0)* a[0] * u;
770 
771  for (int i = 0 ; i < 5 ; i++)
772  r[i] = abs (t[i]) ;
773 
774  k = r[IndiceMax(5, r)] ;
775 
776  for (int i = 1 ; i < 5 ; i++)
777  t[0] = t[0]+t[i];
778 
779  d = (k > epsilon) ? abs (t[0]/std::complex<double>(k,0.0))
780  : 0.0 ;
781 
782  return (d <= epsilon) ? 1 : 0 ;
783 }
784 
785 int Equation::IndiceMin ( int n , double *list )
786 {
787  int iMin ;
788  double xMin ;
789 
790  iMin = 0 ;
791  xMin = list[0] ;
792  for (int i = 1; i < n; i++)
793  {
794  if ( list[i] < xMin )
795  {
796  iMin = i ;
797  xMin = list[i] ;
798  }
799  }
800  return iMin ;
801 }
802 
803 
804 int Equation::IndiceMax ( int n , double *list)
805 {
806  int iMax ;
807  double xMax ;
808 
809  iMax = 0 ;
810  xMax = list[0] ;
811  for (int i = 1; i < n; i++)
812  {
813  if ( list[i] > xMax )
814  {
815  iMax = i ;
816  xMax = list[i] ;
817  }
818  }
819  return iMax ;
820 }
821 
822 int Equation::TestDegree4Quad ( std::complex<double> *a , double epsilon )
823 {
824  double r1, r2, r3 ;
825 
826  r1 = abs (a[1]) ;
827  r2 = abs (a[2]) ;
828  r3 = abs (a[3]) ;
829 
830  return ((r1 < epsilon) && (r2 < epsilon) && (r3 < epsilon)) ? 1 : 0 ;
831 }
832 
833 int Equation::TestDegree4DoubleDouble ( std::complex<double> *a , std::complex<double> *k , double epsilon )
834 {
835  int d4 ;
836  double r0, r1, r2, h[5] ;
837  std::complex<double> u, t[5] ;
838 
839 
840  u = (a[3]* a[3]) ;
841  t[0] = (u* u) * std::complex<double>(3.0 / 16.0, 0.0);
842  t[1] = a[0] * std::complex<double>(4.0,0.0);
843  t[2] = a[3] * a[1];
844  t[3] = u * a[2];
845  t[4] = a[2] * a[2];
846  for (int i = 0 ; i < 5 ; i++)
847  h[i] = abs (t[i]) ;
848 
849  r1 = h[IndiceMax(5, h)] ;
850  u = (t[0]- t[1]) + t[2];
851  u = u - (t[3]- t[4]) ;
852  r2 = (r1 > epsilon) ? abs (u) / r1 : 0.0 ;
853 
854  r1 = abs (k[2]) ;
855  r0 = abs (k[1]) ;
856 
857  if ((r0 >= epsilon) && (r1 < epsilon) && (r2 < epsilon))
858  d4 = 1 ;
859  else
860  d4 = 0 ;
861 
862  return d4 ;
863 }
864 
865 int Equation::TestDegree4SimpleTriple ( std::complex<double> *a , std::complex<double> *k , double epsilon )
866 {
867  int d4 ;
868  double r, r0, r1, r2, h[4] ;
869  std::complex<double> u, t[4] ;
870 
871 
872  t[0] = a[2] * a[2] ;
873  t[1] = a[0] * std::complex<double>(12.0, 0.0);
874  t[2] = (a[1]* a[3]) * std::complex<double>(3.0, 0.0) ;
875  for (int i = 0 ; i < 3 ; i++)
876  h[i] = abs (t[i]) ;
877 
878  r = h[IndiceMax(3, h)] ;
879  u = t[0] + (t[1]- t[2]) ;
880  r1 = (r > epsilon) ? abs (u) / r : 0.0 ;
881 
882  t[0] = a[1] * a[1];
883  t[1] = (a[0]* a[2]) * std::complex<double>(4.0, 0.0) ;
884  u = a[3]* std::complex<double>(3.0, 0.0) ;
885  t[2] = (u* u) * (a[0]* std::complex<double>(3.0, 0.0)) ;
886  t[3] = (a[2]* a[2]) * a[2] ;
887  for (int i = 0 ; i < 4 ; i++)
888  h[i] = abs (t[i]) ;
889  r = h[IndiceMax(4, h)] ;
890  u = ((t[0]- t[1])* std::complex<double>(27.0, 0.0))+ (t[2]- t[3]) ;
891  r2 = (r > epsilon) ? abs (u) / r : 0.0 ;
892 
893  r0 = abs (k[1]) ;
894 
895  if ((r0 >= epsilon) && (r1 < epsilon) && (r2 < epsilon))
896  d4 = 1 ;
897  else
898  d4 = 0 ;
899 
900  return d4 ;
901 }
902 
903 int Equation::TestDegreeSimpleSimpleDouble( std::complex<double> *a , double epsilon )
904 {
905  double r[3] ;
906  std::complex<double> u, v, w ;
907 
908 
909  u = (a[1]* a[1]) - (a[3]* std::complex<double>(4.0, 0.0)) ;
910  u = u* a[3] * u * std::complex<double>(16.0, 0.0);
911  r[0] = abs (u) ;
912 
913  w = pow (a[1], 3.0) * std::complex<double>(4.0, 0.0) ;
914  v = (a[2]* a[2]) * std::complex<double>(27.0, 0.0) ,
915  v = (w+ v) * (a[2]* a[2]) ;
916  r[1] = abs (v) ;
917 
918  w = (a[1]* a[2]) * (a[2]* a[3]) ;
919  w = w * std::complex<double>(144.0, 0.0) ;
920  r[2] = abs (w) ;
921 
922  r[1] = r[IndiceMax(3, r)] ;
923  if (r[1] < epsilon)
924  r[0] = 0.0 ;
925  else if (r[1] <= 1.0)
926  r[0] = abs ((u- v)+ w) ;
927  else
928  r[0] = abs (((u- v)+ w)/ std::complex<double>(r[1], 0.0)) ;
929 
930  return (r[0] < (2.0 * epsilon)) ? 1 : 0 ;
931 }
932 }
int _degree
Equation degree.
Definition: Equation.h:72
ossim_uint32 x
void CreateEquation(int degree, std::complex< double > *coefficients)
Definition: Equation.cpp:47
ossim_uint32 y
int TestDegreeSimpleSimpleDouble(std::complex< double > *a, double epsilon)
Tests whether two simple root and one double root exist in a fourth degree equation.
Definition: Equation.cpp:903
std::vector< int > _order
Definition: Equation.h:81
std::complex< double > Proche(std::complex< double > z, double epsilon)
??
Definition: Equation.cpp:166
int IndiceMax(int n, double *list)
Returns the index of the greater list element.
Definition: Equation.cpp:804
#define abs(a)
Definition: auxiliary.h:74
int IndiceMin(int n, double *list)
Returns the index of the smaller list element.
Definition: Equation.cpp:785
~Equation()
Destructor.
Definition: Equation.cpp:29
os2<< "> n<< " > nendobj n
void Solve3(int d4=0)
Definition: Equation.cpp:300
int TestDegree3Triple(std::complex< double > *a, double epsilon)
Tests whether a triple root exists in a third degree equation.
Definition: Equation.cpp:733
double _normalisationCoefficient
Definition: Equation.h:92
int TestDegree4DoubleDouble(std::complex< double > *a, std::complex< double > *k, double epsilon)
Tests whether two double roots exist in a fourth degree equation.
Definition: Equation.cpp:833
This class manages and solves an equation of the fourth degree.
Definition: Equation.h:26
NormalisationType _normalisationType
Definition: Equation.h:91
int TestDegree4SimpleTriple(std::complex< double > *a, std::complex< double > *k, double epsilon)
Tests whether one simple root and one triple root exist in a fourth degree equation.
Definition: Equation.cpp:865
int TestDegree4Quad(std::complex< double > *a, double epsilon)
Tests whether a quadruple root exists in a fourth degree equation.
Definition: Equation.cpp:822
std::complex< double > * _coefficients
Equation coefficients.
Definition: Equation.h:61
static const double Epsilon
Definition: Equation.h:78
Equation & operator=(const Equation &rhs)
Definition: Equation.cpp:73
Equation()
Constructor.
Definition: Equation.cpp:20
std::complex< double > * _solutions
Definition: Equation.h:82
const std::complex< double > * get_solutions() const
Definition: Equation.h:53
int TestDegree3SimpleDouble(std::complex< double > *a, double epsilon)
Tests whether a double root and a simple root exist in a third degree equation.
Definition: Equation.cpp:758