Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/newmat/solution.cpp @ 4639

Last change on this file since 4639 was 4565, checked in by patrick, 19 years ago

orxonox/trunk: added the newmat library to the project. needs some translation in directory, temp under util/newmat. is needed by the collision detection engine to perform lin alg operations such as eigenvector decomposition. perhaps we will make our own library to do that later.

File size: 5.9 KB
Line 
1//$$ solution.cpp                    // solve routines
2
3// Copyright (C) 1994: R B Davies
4
5
6#define WANT_STREAM                  // include.h will get stream fns
7#define WANT_MATH                    // include.h will get math fns
8
9#include "include.h"
10#include "boolean.h"
11#include "myexcept.h"
12
13#include "solution.h"
14
15#ifdef use_namespace
16namespace RBD_COMMON {
17#endif
18
19
20void R1_R1::Set(Real X)
21{
22   if ((!minXinf && X <= minX) || (!maxXinf && X >= maxX))
23       Throw(SolutionException("X value out of range"));
24   x = X; xSet = true;
25}
26
27R1_R1::operator Real()
28{
29   if (!xSet) Throw(SolutionException("Value of X not set"));
30   Real y = operator()();
31   return y;
32}
33
34unsigned long SolutionException::Select;
35
36SolutionException::SolutionException(const char* a_what) : Exception()
37{
38   Select = Exception::Select;
39   AddMessage("Error detected by solution package\n");
40   AddMessage(a_what); AddMessage("\n");
41   if (a_what) Tracer::AddTrace();
42};
43
44inline Real square(Real x) { return x*x; }
45
46void OneDimSolve::LookAt(int V)
47{
48   lim--;
49   if (!lim) Throw(SolutionException("Does not converge"));
50   Last = V;
51   Real yy = function(x[V]) - YY;
52   Finish = (fabs(yy) <= accY) || (Captured && fabs(x[L]-x[U]) <= accX );
53   y[V] = vpol*yy;
54}
55
56void OneDimSolve::HFlip() { hpol=-hpol; State(U,C,L); }
57
58void OneDimSolve::VFlip()
59   { vpol = -vpol; y[0] = -y[0]; y[1] = -y[1]; y[2] = -y[2]; }
60
61void OneDimSolve::Flip()
62{
63   hpol=-hpol; vpol=-vpol; State(U,C,L);
64   y[0] = -y[0]; y[1] = -y[1]; y[2] = -y[2];
65}
66
67void OneDimSolve::State(int I, int J, int K) { L=I; C=J; U=K; }
68
69void OneDimSolve::Linear(int I, int J, int K)
70{
71   x[J] = (x[I]*y[K] - x[K]*y[I])/(y[K] - y[I]);
72   // cout << "Linear\n";
73}
74
75void OneDimSolve::Quadratic(int I, int J, int K)
76{
77   // result to overwrite I
78   Real YJK, YIK, YIJ, XKI, XKJ;
79   YJK = y[J] - y[K]; YIK = y[I] - y[K]; YIJ = y[I] - y[J];
80   XKI = (x[K] - x[I]);
81   XKJ = (x[K]*y[J] - x[J]*y[K])/YJK;
82   if ( square(YJK/YIK)>(x[K] - x[J])/XKI ||
83      square(YIJ/YIK)>(x[J] - x[I])/XKI )
84   {
85      x[I] = XKJ;
86      // cout << "Quadratic - exceptional\n";
87   }
88   else
89   {
90      XKI = (x[K]*y[I] - x[I]*y[K])/YIK;
91      x[I] = (XKJ*y[I] - XKI*y[J])/YIJ;
92      // cout << "Quadratic - normal\n";
93   }
94}
95
96Real OneDimSolve::Solve(Real Y, Real X, Real Dev, int Lim)
97{
98   enum Loop { start, captured1, captured2, binary, finish };
99   Tracer et("OneDimSolve::Solve");
100   lim=Lim; Captured = false;
101   if (Dev==0.0) Throw(SolutionException("Dev is zero"));
102   L=0; C=1; U=2; vpol=1; hpol=1; y[C]=0.0; y[U]=0.0;
103   if (Dev<0.0) { hpol=-1; Dev = -Dev; }
104   YY=Y;                                // target value
105   x[L] = X;                            // initial trial value
106   if (!function.IsValid(X))
107      Throw(SolutionException("Starting value is invalid"));
108   Loop TheLoop = start;
109   for (;;)
110   {
111      switch (TheLoop)
112      {
113      case start:
114         LookAt(L); if (Finish) { TheLoop = finish; break; }
115         if (y[L]>0.0) VFlip();               // so Y[L] < 0
116
117         x[U] = X + Dev * hpol;
118         if (!function.maxXinf && x[U] > function.maxX)
119            x[U] = (function.maxX + X) / 2.0;
120         if (!function.minXinf && x[U] < function.minX)
121            x[U] = (function.minX + X) / 2.0;
122
123         LookAt(U); if (Finish) { TheLoop = finish; break; }
124         if (y[U] > 0.0) { TheLoop = captured1; Captured = true; break; }
125         if (y[U] == y[L])
126            Throw(SolutionException("Function is flat"));
127         if (y[U] < y[L]) HFlip();             // Change direction
128         State(L,U,C);
129         for (i=0; i<20; i++)
130         {
131            // cout << "Searching for crossing point\n";
132            // Have L C then crossing point, Y[L]<Y[C]<0
133            x[U] = x[C] + Dev * hpol;
134            if (!function.maxXinf && x[U] > function.maxX)
135            x[U] = (function.maxX + x[C]) / 2.0;
136            if (!function.minXinf && x[U] < function.minX)
137            x[U] = (function.minX + x[C]) / 2.0;
138
139            LookAt(U); if (Finish) { TheLoop = finish; break; }
140            if (y[U] > 0) { TheLoop = captured2; Captured = true; break; }
141            if (y[U] < y[C])
142                Throw(SolutionException("Function is not monotone"));
143            Dev *= 2.0;
144            State(C,U,L);
145         }
146         if (TheLoop != start ) break;
147         Throw(SolutionException("Cannot locate a crossing point"));
148
149      case captured1:
150         // cout << "Captured - 1\n";
151         // We have 2 points L and U with crossing between them
152         Linear(L,C,U);                   // linear interpolation
153                                          // - result to C
154         LookAt(C); if (Finish) { TheLoop = finish; break; }
155         if (y[C] > 0.0) Flip();            // Want y[C] < 0
156         if (y[C] < 0.5*y[L]) { State(C,L,U); TheLoop = binary; break; }
157
158      case captured2:
159         // cout << "Captured - 2\n";
160         // We have L,C before crossing, U after crossing
161         Quadratic(L,C,U);                // quad interpolation
162                                          // - result to L
163         State(C,L,U);
164         if ((x[C] - x[L])*hpol <= 0.0 || (x[C] - x[U])*hpol >= 0.0)
165            { TheLoop = captured1; break; }
166         LookAt(C); if (Finish) { TheLoop = finish; break; }
167         // cout << "Through first stage\n";
168         if (y[C] > 0.0) Flip();
169         if (y[C] > 0.5*y[L]) { TheLoop = captured2; break; }
170         else { State(C,L,U); TheLoop = captured1; break; }
171
172      case binary:
173         // We have L, U around crossing - do binary search
174         // cout << "Binary\n";
175         for (i=3; i; i--)
176         {
177            x[C] = 0.5*(x[L]+x[U]);
178            LookAt(C); if (Finish) { TheLoop = finish; break; }
179            if (y[C]>0.0) State(L,U,C); else State(C,L,U);
180         }
181         if (TheLoop != binary) break;
182         TheLoop = captured1; break;
183
184      case finish:
185         return x[Last];
186
187      }
188   }
189}
190
191bool R1_R1::IsValid(Real X)
192{
193   Set(X);
194   return (minXinf || x > minX) && (maxXinf || x < maxX);
195}
196
197#ifdef use_namespace
198}
199#endif
200
Note: See TracBrowser for help on using the repository browser.