00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00030
00031
00032
00033
00034 #ifdef __GNUG__
00035 #pragma implementation "BisectSolver.h"
00036 #endif
00037
00038
00039 #include "mc/mcprec.h"
00040 #ifdef __BORLANDC__
00041 #pragma hdrstop
00042 #endif
00043
00044 #ifndef mcPRECOMP
00045 #include "mc/MathUtils.h"
00046 #include "mc/BisectSolver.h"
00047 #include "mc/MathSystem.h"
00048 #include "mc/MathAndSystem.h"
00049 #include "mc/MathOrSystem.h"
00050 #include "mc/Symbol.h"
00051 #include "mc/Monomial.h"
00052 #endif
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 bool mcBisectSolver::math_WorksOn(const mcMathOrSystem &m) const
00063 {
00064 if (m.math_GetMathSystemType().m_tMath1 != mcMSTL1_EQUATIONS)
00065 return FALSE;
00066
00067
00068
00069
00070 if (m.math_ContainsParameters() ||
00071 m.math_GetCountOfSymbolsType(&mcSymbol::arrUnknowns) > 1)
00072 return FALSE;
00073
00074
00075 return TRUE;
00076 }
00077
00078 mcRealValue mcBisectSolver::math_Bisect(mcMathLine &tosolve, const mcSymbolProperties *unk,
00079 const mcRealValue &a, const mcRealValue &b)
00080 {
00081
00082 mcRealValue fa = tosolve.math_EvaluateAt(unk, a);
00083 mcRealValue fb = tosolve.math_EvaluateAt(unk, b);
00084
00085 return math_Bisect(tosolve, unk, a, b, fa, fb);
00086 }
00087
00088 mcRealValue mcBisectSolver::math_Bisect(mcMathLine &tosolve, const mcSymbolProperties *unk,
00089 const mcRealValue &a, const mcRealValue &b,
00090 const mcRealValue &fa, const mcRealValue &fb)
00091 {
00092 mcSOLVERLOG(wxT("mcBisectSolver::Bisect - bisecting in [%s,%s] where the ")
00093 wxT("function evaluates to [%s,%s]"), mcTXTV(a), mcTXTV(b),
00094 mcTXTV(fa), mcTXTV(fb));
00095
00096 #ifdef __MCDEBUG__
00097 bool check = (a != *mcRealValue::pNAN) && (b != *mcRealValue::pNAN) &&
00098 (fa != *mcRealValue::pNAN) && (fb != *mcRealValue::pNAN);
00099 mcASSERT(check && ((fa*fb) < 0), wxT("Invalid arguments"));
00100 #endif
00101
00102 mcRealValue c = (a+b)/2.0;
00103 if (a == c || b == c)
00104 return c;
00105
00106 mcRealValue err = a-b;
00107 if (err.abs() < m_fDelta)
00108 return c;
00109
00110 mcRealValue fc = tosolve.math_EvaluateAt(unk, c);
00111 mcASSERT(fc != *mcRealValue::pNAN, wxT("Something wrong !!!"));
00112
00113
00114 if (fa*fc < 0)
00115 return math_Bisect(tosolve, unk, a, c, fa, fc);
00116 return math_Bisect(tosolve, unk, c, b, fc, fb);
00117 }
00118
00119 bool mcBisectSolver::math_SolveLine(mcMathLine &p, const mcSymbolProperties *unk,
00120 mcSystemStepArray &steps)
00121 {
00122
00123 mcASSERT(unk != NULL, wxT("We need the main unknown !!"));
00124 mcSOLVERLOG(wxT("mcBisectSolver::math_SolveLine - The unknown is [%s]."), mcTXTP(unk));
00125
00126
00127
00128
00129
00130 mcRealValue a = m_rStart.data_GetRange(0)->math_GetLowerLimitValue(),
00131 b = m_rStart.data_GetRange(0)->math_GetUpperLimitValue();
00132 mcSOLVERLOG(wxT("mcBisectSolver::math_SolveLine - the start range is [%s,%s]."),
00133 mcTXTV(a), mcTXTV(b));
00134
00135
00136 mcRealValue res = math_Bisect(p, unk, a, b);
00137 mcSOLVERLOG(wxT("mcBisectSolver::math_SolveLine - Approximated solution is %s"),
00138 mcTXTV(res));
00139
00140
00141 p.math_SetMathType(mcMMT_EQUATION);
00142 p.data_GetLeftMem().math_WrapSymbol(unk);
00143 p.data_GetRightMem().math_WrapNumber(res);
00144 steps.data_AddLine(p);
00145
00146
00147 return TRUE;
00148 }
00149
00150 bool mcBisectSolver::math_isReady() const
00151 {
00152 if (m_rStart.math_isFinite())
00153 return TRUE;
00154 return FALSE;
00155 }
00156
00157 bool mcBisectSolver::math_SetStartRange(const mcRange &r, const mcMathLine &p,
00158 const mcSymbolProperties *sym)
00159 {
00160 const mcSymbolProperties *unk=sym;
00161
00162
00163
00164 if (!unk) {
00165
00166 for (int i=0; i<mcSymbol::arrUnknowns.data_GetCount(); i++) {
00167 mcSymbolProperties *curr = mcSymbol::arrUnknowns.data_GetSymbol(i);
00168 if (p.math_ContainsSymbol(curr))
00169 unk = curr;
00170 }
00171
00172 if (!unk)
00173 return FALSE;
00174 }
00175
00176
00177
00178
00179
00180 mcRealValue a = r.math_GetLowerLimitValue(),
00181 b = r.math_GetUpperLimitValue();
00182 mcRealValue fa = p.math_EvaluateAt(unk, a);
00183 mcRealValue fb = p.math_EvaluateAt(unk, b);
00184
00185 if (fa*fb > 0)
00186 return FALSE;
00187
00188
00189 m_rStart.data_DeepCopy(r);
00190 return TRUE;
00191 }
00192
00193