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 "PolySolver.h"
00036 #endif
00037
00038
00039 #include "mc/mcprec.h"
00040 #ifdef __BORLANDC__
00041 #pragma hdrstop
00042 #endif
00043
00044 #ifndef mcPRECOMP
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include "mc/mc.h"
00057 #endif
00058
00059
00060
00061
00062
00063 #define mcPOLYSOLVLOG(x) mcMATHLOG(wxT("mcPolySolver::SolveLineFirstDegree [") + \
00064 steps.data_GetLast()->io_GetInlinedExpr() + wxT("] - ") x);
00065
00066
00067
00068
00069
00070
00071
00072
00073 mcPolySolver::mcPolySolver()
00074 {
00075 m_strName = wxT("Polynomial equation solver");
00076 m_strDesc =
00077 wxT("Solves polynomial equations of first degree, ")
00078 wxT("trying to do the minimum possible number ")
00079 wxT("of operations.");
00080 m_nType = mcST_POLYNOMIAL;
00081
00082 math_ResetCoeffArr();
00083 }
00084
00085 void mcPolySolver::math_ResetCoeffArr()
00086 {
00087 for (int i=0; i < mcPOLYSOLVER_MAXDEGREE; i++)
00088 m_pCoeff[i] = mcEmptyElement;
00089 }
00090
00091 void mcPolySolver::math_DeleteCoeffArr()
00092 {
00093 math_ResetCoeffArr();
00094
00095
00096 }
00097
00098 bool mcPolySolver::math_WorksOn(const mcMathOrSystem &m) const
00099 {
00100 if (m.math_GetMathSystemType().m_tMath1 != mcMSTL1_EQUATIONS)
00101 return FALSE;
00102
00103 mcMathType type = m.math_GetMathType();
00104 if (type.m_tMath1 != mcMTL1_POLYNOMIAL ||
00105 type.m_tMath2 != mcMTL2_ALGEBRAIC)
00106 return FALSE;
00107
00108
00109
00110 return TRUE;
00111 }
00112
00113 bool mcPolySolver::math_SolveLine(mcMathLine &p, const mcSymbolProperties *unk,
00114 mcSystemStepArray &steps)
00115 {
00116
00117 mcASSERT(unk != NULL, wxT("we need the main unknown !!"));
00118 mcLOG(wxT("mcPolySolver:math_SolveLine - The unknown is [%s]."), mcTXTP(unk));
00119
00120
00121 mcMATHLOG(wxT("mcPolySolver::SolveLine - I'm detecting the equation degree..."));
00122
00123 mcIntegerValue degree = p.math_GetMaxDegreeFor(unk);
00124 if (!degree.isValid() || degree < 0) {
00125 m_strLastErr = wxT("Cannot retrieve the maximum degree for ") + unk->io_GetInlinedSym();
00126 return FALSE;
00127 }
00128
00129 if (degree > mcPOLYSOLVER_MAXDEGREE) {
00130 m_strLastErr = wxT("Cannot solve an equation with degree > 10 for the unknown ") +
00131 unk->io_GetInlinedSym();
00132 return FALSE;
00133 }
00134
00135
00136 mcASSERT(degree != 0, wxT("The mcPolySolver::math_WorksOn should have returned FALSE !!"));
00137
00138
00139 mcMATHLOG(wxT("mcPolySolver::math_SolveLine - The line [%s] has degree [%d] for [%s]."),
00140 mcTXT(p), degree.GetInt(), mcTXTP(unk));
00141
00142 bool res = TRUE;
00143 switch (degree.GetInt()) {
00144 case 1:
00145 res = math_SolveLineFirstDegree(p, unk, steps);
00146 break;
00147
00148 case 2:
00149 res = math_SolveLineSecondDegree(p, unk, steps);
00150 break;
00151 }
00152
00153
00154 math_DeleteCoeffArr();
00155 steps.data_Check();
00156
00157
00158 return res;
00159 }
00160
00161 void mcPolySolver::math_FindPolyCoeff(const mcMathLine &equ, const mcSymbolProperties *unk,
00162 int degree)
00163 {
00164
00165 math_DeleteCoeffArr();
00166
00167
00168 for (int i=0; i < degree; i++) {
00169
00170
00171 m_pCoeff[i] = equ.data_GetLeftMem().math_GetCoeffOf(unk, i);
00172 }
00173 }
00174
00175 void mcPolySolver::math_GetPolyCoeff(mcMathLine &curr,
00176 const mcSymbolProperties *unk,
00177 mcSystemStepArray &steps)
00178 {
00179
00180 curr.data_Check();
00181
00182
00183
00184 mcMATHLOG(wxT("mcPolySolver::math_GetPolyCoeff - moving symbols"));
00185
00186
00187
00188 curr.math_MoveFreeFrom(unk, FALSE);
00189 curr.math_MoveSymbol(unk, TRUE);
00190 steps.data_AddLine(curr);
00191
00192
00193 mcPOLYSOLVLOG(wxT("simplifying"));
00194 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS, mcEXPSIM_NOFLAGS, curr, steps);
00195
00196
00197 mcPOLYSOLVLOG(wxT("moving symbols again"));
00198
00199 curr.math_MoveNonSymbol(FALSE);
00200 curr.math_MoveParameters(FALSE);
00201 curr.math_MoveConstants(FALSE);
00202 curr.math_MoveSymbol(unk, TRUE);
00203 steps.data_AddLine(curr);
00204
00205
00206 mcPOLYSOLVLOG(wxT("simplifying"));
00207 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS, mcEXPSIM_NOFLAGS, curr, steps);
00208
00209
00210 mcPOLYSOLVLOG(wxT("factorizing"));
00211
00212 curr.math_FactoreOut(unk, *mcPolynomialHelpers::smath_pOne, FALSE);
00213 curr.math_FactoreOutFreeOf(unk, mcEmptyPolynomial, TRUE);
00214 steps.data_AddLine(curr);
00215
00216
00217 mcPOLYSOLVLOG(wxT("simplifying"));
00218 math_DoCompleteSimplification(mcEXPSIM_KEEP_FACTORIZATION,mcEXPSIM_KEEP_FACTORIZATION, curr, steps);
00219
00220
00221 mcPOLYSOLVLOG(wxT("searching the coefficients of the unknown"));
00222 math_FindPolyCoeff(curr, unk, 2);
00223 }
00224
00225 bool mcPolySolver::math_SolveLineFirstDegree(mcMathLine &p,
00226 const mcSymbolProperties *unk,
00227 mcSystemStepArray &steps)
00228 {
00229
00230
00231 math_GetPolyCoeff(p, unk, steps);
00232
00233 if (m_pCoeff[1] == mcEmptyMonomial)
00234 return TRUE;
00235
00236 mcPOLYSOLVLOG(wxT("the coeff #1 is [") + wxString(mcTXT(m_pCoeff[1])) + wxT("]"));
00237
00238
00239 if (!m_pCoeff[1].math_isWrappingOnly(1.0)) {
00240
00241 p.math_SimpleDivideBy(mcPolynomial(m_pCoeff[1]));
00242 steps.data_AddLine(p);
00243 }
00244
00245
00246 mcPOLYSOLVLOG(wxT("I'm beginning last steps"));
00247 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS, mcEXPSIM_NOFLAGS, p, steps);
00248 steps.data_AddKeyLine(p);
00249
00250 return TRUE;
00251 }
00252
00253
00254 bool mcPolySolver::math_SolveLineSecondDegree(mcMathLine &curr,
00255 const mcSymbolProperties *unk,
00256 mcSystemStepArray &steps)
00257 {
00258
00259 curr.data_Check();
00260
00261 curr.math_FactoreOut(unk, *mcPolynomialHelpers::smath_pOne, FALSE);
00262 curr.math_FactoreOutFreeOf(unk, mcEmptyPolynomial, TRUE);
00263
00264
00265
00266
00267
00268 mcPOLYSOLVLOG(wxT("searching the coefficients of the unknown"));
00269 math_FindPolyCoeff(curr, unk, 3);
00270 mcASSERT(m_pCoeff[2] != mcEmptyMonomial, wxT("This is not a 2nd degree equation !"));
00271
00272
00273
00274 mcMonomial a(m_pCoeff[2]), b(m_pCoeff[1]), c(m_pCoeff[0]);
00275 mcPOLYSOLVLOG(wxT("the coeff #2 is [") + wxString(mcTXT(a)) + wxT("]"));
00276
00277
00278 int type = 3;
00279 if (b == mcEmptyMonomial && c == mcEmptyMonomial) type=0;
00280 if (b == mcEmptyMonomial && c != mcEmptyMonomial) type=1;
00281 if (b != mcEmptyMonomial && c == mcEmptyMonomial) type=2;
00282
00283 switch (type) {
00284 case 0:
00285 {
00286
00287
00288
00289
00290 curr.data_GetLeftMem().data_DeleteAll();
00291 curr.data_GetLeftMem().math_WrapSymbol(unk);
00292 steps.data_AddKeyLine(curr);
00293
00294 return TRUE;
00295 }
00296
00297 case 1:
00298 {
00299
00300
00301
00302
00303 curr.math_MoveFreeFrom(unk, FALSE);
00304 steps.data_AddLine(curr);
00305
00306
00307 mcPOLYSOLVLOG(wxT("dividing"));
00308 curr.math_DivideBy(mcPolynomial(a), NULL);
00309 steps.data_AddLine(curr);
00310
00311
00312 mcPOLYSOLVLOG(wxT("simplifying"));
00313 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS, mcEXPSIM_NOFLAGS, curr, steps);
00314
00315
00316 curr.math_SimpleRaiseTo(mcPolynomial(mcFraction(mcNumber(1), mcNumber(2))));
00317
00318
00319 mcPOLYSOLVLOG(wxT("simplifying"));
00320 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS, mcEXPSIM_NOFLAGS, curr, steps);
00321
00322
00323
00324
00325
00326
00327 mcPOLYSOLVLOG(wxT("creating the OR system with the two solutions"));
00328 mcPolynomial tmp(curr.data_GetRightMem());
00329 mcPolynomial left(unk);
00330
00331
00332
00333
00334 math_SplitInTwoEquations(left, tmp, left, -mcPolynomial(tmp), steps);
00335
00336
00337
00338
00339 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS, mcEXPSIM_NOFLAGS, curr, steps);
00340
00341 return TRUE;
00342 }
00343
00344 case 2:
00345 {
00346
00347
00348
00349
00350 curr.math_FactoreOutAll(FALSE);
00351 mcASSERT(curr.math_isFactorized(), wxT("Something wrong"));
00352 steps.data_AddLine(curr);
00353
00354
00355 mcArrayEntry idx = curr.data_GetLeftMem().
00356 math_GetIndexOf(0, mcMonomial(mcSymbol(unk)), TRUE);
00357 curr.data_GetLeftMem().math_Remove(
00358 curr.data_GetLeftMem().math_GetMonomialIdxFromEntry(idx), FALSE);
00359
00360
00361 mcMathLine solved(unk, mcRealValue(0.0));
00362 math_SplitInTwoEquations(solved, curr, steps);
00363
00364
00365 mcSystemStepArray semisteps1, semisteps2;
00366
00367
00368 semisteps1.data_AddLine(solved);
00369
00370
00371 mcPOLYSOLVLOG(wxT("final solving of second equation"));
00372 if (!math_SolveLineFirstDegree(curr, unk, semisteps2))
00373 return FALSE;
00374 mcMATHLOG(wxT("\n\n%s\n\n"), mcTXT(semisteps2));
00375
00376
00377 steps.math_AppendCombinationOf(semisteps1, semisteps2, mcLO_OR);
00378
00379 return TRUE;
00380 }
00381
00382 case 3:
00383 {
00384
00385 mcPOLYSOLVLOG(wxT("the coeff #1 is [") + wxString(mcTXT(b)) + wxT("]"));
00386 mcPOLYSOLVLOG(wxT("the coeff #0 is [") + wxString(mcTXT(c)) + wxT("]"));
00387
00388
00389 mcPOLYSOLVLOG(wxT("multiplying by 4a"));
00390 mcPolynomial tmp(4);
00391 tmp *= a;
00392 curr *= tmp;
00393 steps.data_AddKeyLine(curr);
00394
00395
00396 mcPOLYSOLVLOG(wxT("simplifying"));
00397 math_DoCompleteSimplification(mcEXPSIM_NOFLAGS,mcEXPSIM_NOFLAGS, curr, steps);
00398
00399
00400 mcPOLYSOLVLOG(wxT("adding and subtracting b^2"));
00401
00402 curr.data_GetLeftMem() += mcPolynomial(b)^2;
00403 curr.data_GetLeftMem() -= mcPolynomial(b)^2;
00404 steps.data_AddKeyLine(curr);
00405
00406
00407
00408
00409
00410 mcPOLYSOLVLOG(wxT("picking up the quadratic"));
00411
00412
00413 mcPolynomial &l = curr.data_GetLeftMem();
00414 mcSymbol sym((mcSymbolProperties *)unk);
00415
00416 mcArrayEntry idx1 = l.math_GetIndexOf(0, mcMonomial(b)^2, TRUE);
00417 l.math_Remove(l.math_GetMonomialIdxFromEntry(idx1), TRUE);
00418
00419 mcMonomial square(a^2);
00420 square *= mcNumber(4);
00421 square *= mcMonomial(sym^mcPolynomial(mcNumber(2)));
00422 mcArrayEntry idx2 = l.math_GetIndexOf(0, square, TRUE);
00423 l.math_Remove(l.math_GetMonomialIdxFromEntry(idx2), TRUE);
00424
00425 mcMonomial product(a*b);
00426 product *= mcNumber(4);
00427 product *= sym;
00428 mcArrayEntry idx3 = l.math_GetIndexOf(0, product, TRUE);
00429 l.math_Remove(l.math_GetMonomialIdxFromEntry(idx3), TRUE);
00430
00431
00432 mcPolynomial contents(2);
00433 contents *= a;
00434 contents *= sym;
00435 contents += b;
00436 mcBracket br(contents);
00437 br ^= mcPolynomial(mcNumber(2));
00438 curr.math_MoveAll(FALSE);
00439 curr.data_GetLeftMem() += mcPolynomial(br);
00440 steps.data_AddKeyLine(curr);
00441
00442
00443 mcPOLYSOLVLOG(wxT("simplifying"));
00444 math_DoCompleteSimplification(mcEXPSIM_KEEP_FACTORIZATION, mcEXPSIM_KEEP_FACTORIZATION, curr, steps);
00445
00446
00447
00448
00449
00450
00451
00452 mcPOLYSOLVLOG(wxT("applying the square root"));
00453
00454 curr.math_SimpleRaiseTo(mcPolynomial(mcFraction(mcNumber(1), mcNumber(2))));
00455
00456
00457 mcMathLine equ1(curr), equ2(curr);
00458 equ2.data_GetRightMem().math_ChangeAllSigns();
00459 mcMathOrSystem *step = new mcMathOrSystem();
00460
00461
00462 step->data_AddLineToNewAndSystem(new mcMathLine(equ1));
00463 step->data_AddLineToNewAndSystem(new mcMathLine(equ2));
00464 steps.data_AddSys(step);
00465
00466
00467 mcSystemStepArray semisteps1, semisteps2;
00468
00469
00470 mcPOLYSOLVLOG(wxT("final solving of first equation"));
00471 if (!math_SolveLineFirstDegree(equ1, unk, semisteps1))
00472 return FALSE;
00473 mcMATHLOG(wxT("\n\n%s\n\n"), mcTXT(semisteps1));
00474
00475
00476 mcPOLYSOLVLOG(wxT("final solving of second equation"));
00477 if (!math_SolveLineFirstDegree(equ2, unk, semisteps2))
00478 return FALSE;
00479 mcMATHLOG(wxT("\n\n%s\n\n"), mcTXT(semisteps2));
00480
00481
00482 steps.math_AppendCombinationOf(semisteps1, semisteps2, mcLO_OR);
00483
00484
00485 return TRUE;
00486 }
00487 }
00488
00489 return TRUE;
00490 }
00491
00492
00493