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 "Polynomial.h"
00036 #endif
00037
00038
00039
00040 #include "mc/mcprec.h"
00041 #ifdef __BORLANDC__
00042 #pragma hdrstop
00043 #endif
00044
00045 #ifndef mcPRECOMP
00046 #include <wx/tokenzr.h>
00047 #include "mc/Polynomial.h"
00048 #include "mc/Monomial.h"
00049 #include "mc/MathUtils.h"
00050 #endif
00051
00052
00053
00054
00055 #include "mc/Bracket.h"
00056 #include "mc/Number.h"
00057 #include "mc/Fraction.h"
00058 #include "mc/Parenthesis.h"
00059 #include "mc/Symbol.h"
00060
00061
00062 mcIMPLEMENT_MAIN_CLASS(mcPolynomial, mcElementArray);
00063
00064
00065
00066
00067 int mcPolynomialHelpers::sgui_nSpaceBetween = 2;
00068 mcPolynomial *mcPolynomialHelpers::smath_pOne = NULL;
00069 mcPolynomial *mcPolynomialHelpers::smath_pEmpty = NULL;
00070
00071
00072
00073 mcPolynomial mcEmptyPolynomial((mcPolynomialHelpers*)NULL);
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00092 bool isPolynomialOkay(const mcElement &p)
00093 {
00094 static bool lastwasop = FALSE;
00095
00096 if (p.data_GetType() != mcET_MONOMIAL &&
00097 p.data_GetType() != mcET_ADDOP &&
00098 p.data_GetType() != mcET_SUBOP) {
00099
00100
00101 return FALSE;
00102 }
00103
00104 if ((p.data_GetType() == mcET_ADDOP ||
00105 p.data_GetType() == mcET_SUBOP) && !lastwasop) {
00106
00107 lastwasop = TRUE;
00108
00109 } else if (p.data_GetType() == mcET_MONOMIAL && lastwasop) {
00110
00111 lastwasop = FALSE;
00112
00113 } else {
00114
00115
00116
00117
00118 return FALSE;
00119 }
00120
00121 return TRUE;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 #ifdef __MCDEBUG__
00134
00135 void mcPolynomialHelpers::data_Check() const
00136 {
00137
00138 bool b = FALSE;
00139 if (data_GetCount() > 0 && data_isOp(0))
00140 b = TRUE;
00141
00142
00143
00144 if (!b && data_GetCount() > 0) {
00145
00146 mcASSERT(!data_isOp(0),
00147 wxT("If 'b' is FALSE, the first element should be a non-op !!!"));
00148 mcASSERT(data_Get(0).data_GetType() == mcET_MONOMIAL,
00149 wxT("If the first element is not an op, then it should be a mcMonomial !!!"));
00150 }
00151
00152 #ifdef mcENABLE_VERBOSE_CHECK
00153 mcLOG(wxT("mcPolynomialHelpers::data_Check - checking [%s]"), mcTXTTHIS);
00154 #endif
00155 mcASSERT(data_ScanArray(isPolynomialOkay, b),
00156 wxT("Not all the monomials in the array are ") \
00157 wxT("separed by a mcAddOp or a mcSubOp"));
00158
00159
00160
00161 mcElementArrayHelpers::data_Check();
00162 }
00163
00164 #endif
00165
00166 bool mcPolynomialHelpers::data_isWrappingOnly(mcElementType t) const
00167 {
00168 if (data_GetCount() > 1)
00169 return FALSE;
00170
00171
00172
00173 if (data_Get(0).data_GetType() == t)
00174 return TRUE;
00175
00176
00177
00178
00179
00180 if (data_Get(0).data_GetType() == mcET_MONOMIAL &&
00181 ((const mcMonomial &)data_Get(0)).data_isWrappingOnly(t))
00182 return TRUE;
00183 return FALSE;
00184 }
00185
00186 const mcElement &mcPolynomialHelpers::data_GetWrapped(mcElementType t) const
00187 {
00188
00189
00190 if (!data_isWrappingOnly(t))
00191 return mcEmptyElement;
00192
00193
00194
00195 if (data_Get(0).data_GetType() == t)
00196 return data_Get(0);
00197
00198
00199 return ((const mcMonomial &)data_GetElemOfType(0, mcET_MONOMIAL)).data_GetWrapped(t);
00200 }
00201
00202 bool mcPolynomialHelpers::math_isWrappingOnly(mcElementType t) const
00203 {
00204
00205 if (math_GetCount() != 1)
00206 return FALSE;
00207 if (math_Get(0).data_GetType() == t)
00208 return TRUE;
00209 if (math_Get(0).math_isWrappingOnly(t))
00210 return TRUE;
00211 return FALSE;
00212 }
00213
00214 const mcElement &mcPolynomialHelpers::math_GetWrapped(mcElementType t) const
00215 {
00216
00217 if (!math_isWrappingOnly(t))
00218 return mcEmptyElement;
00219 if (math_Get(0).data_GetType() == t)
00220 return math_Get(0);
00221 return math_Get(0).math_GetWrapped(t);
00222 }
00223
00224 bool mcPolynomialHelpers::data_CreateFirstOp()
00225 {
00226 if (!data_isArrayEmpty() && data_isOp(0))
00227 return FALSE;
00228
00229
00230
00231 data_MoveElemRight(0);
00232 data_AddNewOp(mcET_ADDOP, 0);
00233 return TRUE;
00234 }
00235
00236 void mcPolynomialHelpers::data_DeleteFirstOp()
00237 {
00238 if (data_isArrayEmpty() || !data_isOp(0))
00239 return;
00240
00241 data_DeleteFirst(1);
00242 }
00243
00244 mcElement &mcPolynomialHelpers::data_AddNewWrappedElement(mcElementType t,
00245 bool bOverwrite, int pos)
00246 {
00247 mcASSERT(t != mcET_MONOMIAL, wxT("Cannot nest monomials"));
00248
00249
00250 mcElement res = mcElementHelpers::data_NewElem(t);
00251 int n = data_AddNewMonomialContaining(&res, pos, bOverwrite);
00252 if (n == -1) return mcEmptyElement;
00253
00254
00255 mcMonomial &m = (mcMonomial &)data_Get(pos);
00256 return m.data_Get(n);
00257 }
00258
00259 void mcPolynomialHelpers::data_DetachAndShiftMonomial(int n)
00260 {
00261
00262 mcASSERT(data_Get(n).data_GetType() == mcET_MONOMIAL,
00263 wxT("This function works on monomials only"));
00264
00265
00266 data_Detach(n);
00267 data_MoveElemLeft(n);
00268
00269 if (n > 0 && data_isOp(n-1)) {
00270 data_Detach(n-1);
00271 data_MoveElemLeft(n-1);
00272 }
00273 }
00274
00275 int mcPolynomialHelpers::data_AddNewMonomialContaining(mcElement *contents,
00276 int n, int pos, bool bOverwrite)
00277 {
00278
00279 mcMonomial m;
00280
00281
00282 mcASSERT(n > 0, wxT("Cannot add zero elements"));
00283 int idx = m.data_AddElements(contents, n);
00284
00285
00286 data_AddElements((mcElement *)(&m), 1, pos, bOverwrite);
00287 return idx;
00288 }
00289
00290 bool mcPolynomialHelpers::data_ReplaceParentheses(int leftm, int leftidx,
00291 int rightm, int rightidx,
00292 bool bMoveOnBracketEnd)
00293 {
00294 const mcMonomial &left = (const mcMonomial &)data_Get(leftm);
00295 const mcMonomial &right = (const mcMonomial &)data_Get(rightm);
00296 const mcParenthesis &rightp = (const mcParenthesis &)right.data_Get(rightidx);
00297 mcLOG(wxT("mcPolynomialHelpers::data_ReplaceParentheses - ")
00298 wxT("the monomial containing the left bracket is [%s]"), mcTXT(left));
00299 mcLOG(wxT("mcPolynomialHelpers::data_ReplaceParentheses - ")
00300 wxT("the monomial containing the right bracket is [%s]"), mcTXT(right));
00301
00302
00303
00304 mcPolynomial contents;
00305
00306
00307
00308
00309 if (left.data_GetCount() - leftidx > 0) {
00310
00311 int n = left.data_GetCount() - leftidx - 1;
00312
00313 if (rightm == leftm) {
00314
00315
00316
00317 n -= left.data_GetCount()-rightidx;
00318 }
00319
00320 if (n > 0)
00321 contents.data_AddNewMonomialContaining(
00322 left.data_GetArray(leftidx+1),
00323 n,
00324 -1,
00325 TRUE);
00326 }
00327
00328
00329
00330
00331 if (rightm-leftm > 0) {
00332
00333 contents.data_AddElements(
00334 data_GetArray(leftm+1),
00335 rightm-leftm-1);
00336 }
00337
00338
00339
00340 if (rightm != leftm && rightidx > 0) {
00341
00342 contents.data_AddNewMonomialContaining(
00343 right.data_GetArray(),
00344 rightidx);
00345
00346 }
00347
00348
00349 if (contents.data_isArrayEmpty()) {
00350
00351
00352
00353
00354
00355 contents.data_AddNewEmptyMonomial();
00356 }
00357
00358
00359
00360 if (((const mcMonomial &)contents.data_GetElemOfType(0, mcET_MONOMIAL)).data_isArrayEmpty()) {
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 contents.data_DeleteFirst(1);
00372 }
00373
00374
00375 mcBracket br;
00376 br.data_SetContent(contents);
00377
00378
00379
00380 if (rightp.hlp()->mdata_pTmpExp != mcEmptyElement &&
00381 !rightp.hlp()->mdata_pTmpExp.data_isArrayEmpty()) {
00382
00383 mcLOG(wxT("mcPolynomialHelpers::data_ReplaceParentheses - ")
00384 wxT("the exponent of the bracket is [%s]"), mcTXT(rightp.hlp()->mdata_pTmpExp));
00385 br.data_SetExpSub(TRUE, rightp.hlp()->mdata_pTmpExp);
00386 }
00387
00388 mcLOG(wxT("mcPolynomialHelpers::data_ReplaceParentheses - ")
00389 wxT("the new bracket is [%s]"), mcTXT(br));
00390 br.data_Check();
00391
00392
00393
00394 mcMonomial &m = (mcMonomial &)left;
00395
00396
00397 int cursoridx = -1;
00398 if (rightm != leftm) {
00399
00400 m.data_DeleteLast(m.data_GetCount()-leftidx);
00401 m.data_AddElements((mcElement*)(&br), 1);
00402 cursoridx = m.data_GetCount()-1;
00403
00404 } else {
00405
00406
00407
00408 m.data_AddElements((mcElement*)(&br), 1, leftidx, TRUE);
00409 cursoridx = leftidx;
00410
00411
00412
00413 for (int g=leftidx+1; g < rightidx+1; g++) {
00414
00415 m.data_Delete(leftidx+1);
00416 m.data_MoveElemLeft(leftidx+1);
00417 }
00418 }
00419
00420
00421
00422 if (mcMathCore::Get()->isGUIEnabled()) {
00423 if (bMoveOnBracketEnd) {
00424
00425
00426
00427 m.gui_SetCursorPos(mcCP_END);
00428
00429 } else {
00430
00431 m.gui_SetCursorOnElemBegin(cursoridx);
00432
00433
00434
00435
00436
00437
00438 m.gui_MoveCursor(mcMCF_RIGHT, mcMCF_NOMODIFIERS);
00439 }
00440 }
00441
00442
00443
00444 if (rightm != leftm) {
00445
00446 m.data_AddElements(
00447 right.data_GetArray(rightidx+1),
00448 right.data_GetCount()-rightidx-1);
00449
00450
00451 data_Delete(leftm+1);
00452 data_MoveElemLeft(leftm+1);
00453 }
00454
00455
00456
00457 for (int g=leftm+1; g < rightm; g++) {
00458
00459 data_Delete(leftm+1);
00460 data_MoveElemLeft(leftm+1);
00461 }
00462
00463 mcLOG(wxT("mcPolynomialHelpers::data_ReplaceParentheses - ")
00464 wxT("after removing replaced elements, I'm set to [%s]"), mcTXTTHIS);
00465
00466
00467 if (mcMathCore::Get()->isGUIEnabled())
00468 mgui_nCursorPos = leftm;
00469
00470
00471 data_Check();
00472 return TRUE;
00473 }
00474
00475 bool mcPolynomialHelpers::data_ReplaceParentheses(bool bMoveOnBracketEnd)
00476 {
00477 bool bFoundFirst = FALSE;
00478
00479 int monomialidx = -1,
00480 bracketidx = -1;
00481
00482 int bridx = -1,
00483 i;
00484
00485 for (i=0; i < data_GetCount(); i++) {
00486
00487
00488 if (data_Get(i).data_GetType() != mcET_MONOMIAL)
00489 continue;
00490
00491
00492 const mcMonomial &m = (const mcMonomial &)data_Get(i);
00493
00494
00495 for (int j=0, max=m.data_GetCount(); j < max; j++) {
00496
00497 const mcElement &curr = m.data_Get(j);
00498 if (curr.data_GetType() != mcET_PARENTHESIS)
00499 continue;
00500
00501
00502 bridx = j;
00503 const mcParenthesis &p = m.data_Get(bridx);
00504
00505 if (!bFoundFirst) {
00506
00507
00508 if (!p.data_isLeftBracket())
00509 continue;
00510
00511
00512
00513 bFoundFirst = TRUE;
00514 monomialidx = i;
00515 bracketidx = bridx;
00516
00517
00518
00519
00520
00521
00522 } else {
00523
00524
00525 if (p.data_isLeftBracket()) {
00526
00527
00528
00529
00530 monomialidx = i;
00531 bracketidx = bridx;
00532 continue;
00533 }
00534
00535
00536 return data_ReplaceParentheses(monomialidx, bracketidx, i,
00537 bridx, bMoveOnBracketEnd);
00538 }
00539 }
00540 }
00541
00542
00543 return FALSE;
00544 }
00545
00546 void mcPolynomialHelpers::data_ReplaceAllParentheses()
00547 {
00548 bool exit = FALSE;
00549 while (!exit) {
00550
00551
00552
00553 exit = !data_ReplaceParentheses(FALSE);
00554 }
00555 }
00556
00557 void mcPolynomialHelpers::gui_ReplaceBracket(const mcBracket &br, bool left)
00558 {
00559 mcGUILOG(wxT("mcPolynomialHelpers::gui_ReplaceBracket - replacing the %s of [%s]"),
00560 (left ? wxT("left") : wxT("right")), mcTXT(br));
00561 mcPolynomial contents(br.data_GetConstContent());
00562 mcMonomial &m = mcEmptyMonomial;
00563
00564 int monomialidx = -1,
00565 pcursoridx = -1,
00566 bridx = -1,
00567 mcursoridx = -1;
00568
00569
00570 mcASSERT(contents.data_GetCount() > 0, wxT("Cannot break an empty bracket..."));
00571
00572
00573
00574 for (int i=0; i < data_GetCount(); i++) {
00575
00576
00577 if (data_Get(i).data_GetType() != mcET_MONOMIAL)
00578 continue;
00579 const mcMonomial &tocheck = (const mcMonomial &)data_GetConst(i);
00580
00581
00582 if ((bridx = tocheck.data_GetIndexOf(br)) != -1) {
00583 monomialidx = i;
00584 pcursoridx = monomialidx;
00585 mcursoridx = bridx-1;
00586 m = tocheck;
00587 break;
00588 }
00589 }
00590
00591 mcASSERT(m != mcEmptyElement, wxT("Something wrong"));
00592 mcGUILOG(wxT("mcPolynomialHelpers::gui_ReplaceBracket - the monomial ")
00593 wxT("with the bracket to replace is [%s]"), mcTXT(m));
00594 m.data_Delete(bridx);
00595 m.data_MoveElemLeft(bridx);
00596
00597
00598
00599 if (!left) {
00600
00601 mcParenthesis left;
00602 left.data_SetAsLeftBracket();
00603 left.data_AddProperty(mcEP_INITIALIZED);
00604 m.data_AddElements(&left, 1, bridx);
00605 bridx++;
00606
00607 mcGUILOG(wxT("mcPolynomialHelpers::gui_ReplaceBracket - the monomial is [%s]"), mcTXT(m));
00608 }
00609
00610
00611
00612 mcMonomial &first = (mcMonomial &)contents.data_GetElemOfType(0, mcET_MONOMIAL);
00613 if (contents.data_Get(0).data_GetType() == mcET_MONOMIAL) {
00614 m.data_AddElements(first.data_GetArray(),
00615 first.data_GetCount(), bridx);
00616
00617
00618
00619 contents.data_Delete(0);
00620 contents.data_MoveElemLeft(0);
00621 }
00622
00623 mcGUILOG(wxT("mcPolynomialHelpers::gui_ReplaceBracket - the monomial is [%s]"), mcTXT(m));
00624
00625
00626 if (contents.data_GetCount() > 1) {
00627
00628 data_Merge(contents);
00629 monomialidx += contents.data_GetCount();
00630 }
00631
00632 m = (mcMonomialHelpers *)data_Get(monomialidx).hlp();
00633
00634
00635
00636 if (left) {
00637 mcParenthesis right;
00638 right.data_SetAsRightBracket();
00639 right.data_AddProperty(mcEP_INITIALIZED);
00640 m.data_AddElements(&right, 1, bridx+1);
00641
00642 mcGUILOG(wxT("mcPolynomialHelpers::gui_ReplaceBracket - the monomial is [%s]"), mcTXT(m));
00643 }
00644
00645
00646
00647 if (!left) {
00648 mgui_nCursorPos = monomialidx;
00649
00650
00651 if (bridx+1 >= m.data_GetCount())
00652 m.gui_SetCursorPos(mcCP_END);
00653 else
00654 m.gui_SetCursorOnElemEnd(bridx+1);
00655 }
00656
00657 if (left) {
00658
00659
00660 mgui_nCursorPos = pcursoridx;
00661 m = (mcMonomialHelpers *)data_Get(pcursoridx).hlp();
00662
00663 if (mcursoridx < 0) {
00664
00665
00666
00667 m.gui_SetCursorPos(mcCP_BEGIN);
00668
00669 } else {
00670
00671
00672
00673 m.gui_SetCursorOnElemEnd(mcursoridx);
00674 }
00675 }
00676
00677
00678 data_Check();
00679 mcGUILOG(wxT("mcPolynomialHelpers::gui_ReplaceBracket - we are now ")
00680 wxT("set to [%s]"), mcTXTTHIS);
00681 }
00682
00683 int mcPolynomialHelpers::data_FindMonomialContaining(int occ, const mcElement &elem) const
00684 {
00685 int n = -1;
00686
00687 for (int i=0; i < data_GetCount(); i++) {
00688
00689
00690 if (data_Get(i).data_GetType() != mcET_MONOMIAL) continue;
00691
00692
00693 if ((n = mcMonomial(data_Get(i)).data_GetIndexOf(elem)) != -1) {
00694 if (occ == 0)
00695 return n;
00696 occ--;
00697 }
00698 }
00699
00700
00701 return -1;
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 bool mcPolynomialHelpers::gui_isArrayEmpty()
00715 {
00716 if (data_isArrayEmpty() || (data_GetCount() == 1 && data_isOp(0)))
00717 return TRUE;
00718 return FALSE;
00719 }
00720
00721 int mcPolynomialHelpers::gui_ExDraw(wxDC &dc, int x, int y, long flags, const wxPoint &pt, int cl) const
00722 {
00723 mcGUILOG(wxT("mcPolynomialHelpers::gui_ExDraw [%s]"), mcTXTTHIS);
00724 int a = gui_GetSelElemCount();
00725
00726
00727
00728
00729 if (a > 1) {
00730
00731
00732 int mflags = flags & ~mcDRW_ALLOW_TOTAL_SELECTION;
00733
00734
00735 int w, n = mcElementArrayHelpers::gui_ExDraw(dc, x, y, mflags, pt, cl);
00736
00737
00738
00739 if ((w=gui_DrawSelection(dc, x, y, flags, pt, cl)) != mcDRW_NOACTIVEELEM)
00740 n = w;
00741 return n;
00742 }
00743
00744 return mcElementArrayHelpers::gui_ExDraw(dc, x, y, flags, pt, cl, FALSE, -1, TRUE);
00745 }
00746
00747 void mcPolynomialHelpers::gui_ExOnSelect(wxDC &dc, wxRect &rc, int cl)
00748 {
00749
00750 mcElementArrayHelpers::gui_ExOnSelect(dc, rc, cl);
00751
00752
00753
00754 for (int a=gui_GetSelStart(), b=gui_GetSelEnd(); a < b; a++)
00755 if (data_Get(a).gui_isAllSelected())
00756 if (a > 0 && data_isOp(a-1))
00757 data_Get(a-1).gui_SelectAll();
00758 }
00759
00760 int mcPolynomialHelpers::gui_AddNewElement(mcElementType type, const mcKey &key, int pos)
00761 {
00762
00763 if (pos == -1) pos = data_GetCount();
00764
00765
00766 mcASSERT(type == mcET_MONOMIAL || type == mcET_ADDOP || type == mcET_SUBOP,
00767 wxT("Cannot create something which is not a mcOperator or a mcMonomial !!!!"));
00768 mcElementArrayHelpers::gui_AddNewElement(type, key, pos);
00769
00770
00771 if (type == mcET_ADDOP || type == mcET_SUBOP) {
00772 if (pos == data_GetCount()-1 || data_isOp(pos+1)) {
00773
00774
00775
00776
00777
00778 pos++;
00779 data_MoveElemRight(pos);
00780 gui_AddNewEmptyMonomial(pos);
00781
00782 } else if (pos > 0 && data_isOp(pos-1)) {
00783
00784
00785
00786
00787
00788
00789
00790 data_MoveElemRight(pos);
00791 gui_AddNewEmptyMonomial(pos);
00792
00793 } else if (pos == 0) {
00794
00795
00796
00797
00798
00799
00800 pos++;
00801 }
00802 }
00803
00804 gui_RecalcSize();
00805 return pos;
00806 }
00807
00808 mcInputRes mcPolynomialHelpers::gui_Input(const mcKey &ev, mcElement *newelem)
00809 {
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820 if (gui_GetCursorPos().isBegin() || data_isWrappingOnly(mcET_EMPTYBOX)) {
00821 mcElementType n = mcElementHelpers::gui_isKeyBeginKey(ev);
00822
00823 if (n == mcET_ADDOP || n == mcET_SUBOP) {
00824
00825 bool replace = FALSE;
00826
00827
00828
00829
00830 if (data_GetCount() > 0 && data_isOp(0))
00831 replace = TRUE;
00832 mcElement &e = data_AddNewElement(n, replace, 0);
00833
00834
00835 e.gui_RecalcSize();
00836
00837
00838 if (!replace) mgui_nCursorPos++;
00839 gui_CheckCursorPos();
00840
00841 gui_RecalcSize();
00842 return mcIR_OKAY;
00843 }
00844
00845 }
00846
00847
00848 mcElementType n = mcElementHelpers::gui_isKeyBeginKey(ev);
00849 if (n == mcET_PARENTHESIS)
00850 gui_OnNewParenthesis(mcBracketHelpers::gui_isLeftParenthesis(ev.GetKeyCode()));
00851
00852
00853 mcInputRes r = mcElementArrayHelpers::gui_Input(ev, newelem);
00854
00855
00856 if (mgui_bRemoveParenthesis) {
00857 data_ReplaceParentheses(!mgui_bMoveCursorAtBracketBegin);
00858 mgui_bRemoveParenthesis = FALSE;
00859 gui_DeepRecalcSize();
00860 }
00861
00862 if (mgui_pBracketToReplace != mcEmptyElement) {
00863 gui_ReplaceBracket(mgui_pBracketToReplace, mgui_bRemoveLeftParenthesis);
00864 mgui_pBracketToReplace = NULL;
00865 gui_DeepRecalcSize();
00866 }
00867
00868 return r;
00869 }
00870
00871 mcInputRes mcPolynomialHelpers::gui_BackInput(const mcKey &key, mcElement *pnewelem, int n)
00872 {
00873 int last;
00874 bool b;
00875
00876 switch (n) {
00877 case mcIR_OKAY:
00878 break;
00879
00880 case mcIR_REPLACE_THIS:
00881 if (mgui_nCursorPos == 0) {
00882 mcMathCore::Get()->SyntaxError(wxT("Cannot data_Delete this element"));
00883 return mcIR_OKAY;
00884 }
00885
00886
00887 data_Delete(mgui_nCursorPos);
00888 data_MoveElemLeft(mgui_nCursorPos);
00889
00890
00891 data_AddElements(pnewelem, 1, mgui_nCursorPos-1, TRUE);
00892 mgui_nCursorPos--;
00893 (*pnewelem) = NULL;
00894
00895
00896 return mcIR_OKAY;
00897
00898 case mcIR_DELETE_THIS:
00899
00900 if (mgui_nCursorPos == 0 && data_GetCount() > 1) {
00901
00902
00903
00904 return mcIR_DELETE_PREVIOUS;
00905 }
00906
00907
00908 data_Delete(mgui_nCursorPos);
00909 data_MoveElemLeft(mgui_nCursorPos);
00910
00911 if (mgui_nCursorPos > 0) {
00912
00913
00914 mcASSERT(data_isOp(mgui_nCursorPos-1), wxT("An operator was expected"));
00915 data_Delete(mgui_nCursorPos-1);
00916 data_MoveElemLeft(mgui_nCursorPos-1);
00917 mgui_nCursorPos--;
00918
00919
00920 if (mgui_nCursorPos == 0) {
00921
00922
00923
00924
00925 data_MoveElemRight(0);
00926 gui_AddNewEmptyMonomial(0);
00927 return mcIR_OKAY;
00928 }
00929 }
00930
00931
00932
00933 mgui_nCursorPos--;
00934
00935 if (mgui_nCursorPos >= 0) {
00936 if (mcMathCore::Get()->m_pCancelKey->MatchKey(key))
00937 data_Get(mgui_nCursorPos).gui_SetCursorPos(mcCP_BEGIN);
00938 else if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key))
00939 data_Get(mgui_nCursorPos).gui_SetCursorPos(mcCP_END);
00940 }
00941
00942
00943
00944 if (data_isArrayEmpty())
00945 return mcIR_DELETE_THIS;
00946 break;
00947
00948 case mcIR_DELETE_PREVIOUS:
00949
00950
00951
00952
00953
00954 if (mgui_nCursorPos == 0) {
00955
00956
00957 return mcIR_DELETE_PREVIOUS;
00958 }
00959
00960
00961 if (mgui_nCursorPos == 1) {
00962
00963
00964
00965
00966
00967
00968 mcASSERT(data_isOp(0), wxT("If the first element is not an operator, cursor")
00969 wxT("is acutally placed on an operator..."));
00970 data_Delete(0);
00971 data_MoveElemLeft(0);
00972 mgui_nCursorPos--;
00973 return mcIR_OKAY;
00974 }
00975
00976
00977 b = mcMonomial(data_Get(mgui_nCursorPos-2)).gui_MergeWith(data_Get(mgui_nCursorPos));
00978 mcASSERT(b, wxT("Two monomials should always be able to merge..."));
00979
00980
00981 data_Delete(mgui_nCursorPos-1);
00982 data_Delete(mgui_nCursorPos);
00983 data_MoveElemLeft(mgui_nCursorPos);
00984 data_MoveElemLeft(mgui_nCursorPos-1);
00985
00986
00987 mgui_nCursorPos -= 2;
00988
00989
00990 data_Check();
00991 gui_CheckCursorPos();
00992 break;
00993
00994 case mcIR_DELETE_NEXT:
00995
00996
00997
00998
00999
01000 last = data_GetCount()-1;
01001 if (mgui_nCursorPos == last) {
01002
01003
01004 return mcIR_DELETE_NEXT;
01005 }
01006
01007
01008 mcASSERT(mgui_nCursorPos < last-1, wxT("If the monomial cannot end with an operator ")
01009 wxT("and the cursor is not on the last monomial, it must be placed ")
01010 wxT("on the previous monomial, which should be at data_GetCount()-2"));
01011
01012
01013 b = mcMonomial(data_Get(mgui_nCursorPos)).gui_MergeWith(data_Get(mgui_nCursorPos+2));
01014 mcASSERT(b, wxT("Two monomials should always be able to merge..."));
01015 mcUNUSED(b);
01016
01017
01018 data_Delete(mgui_nCursorPos+1);
01019 data_Delete(mgui_nCursorPos+2);
01020 data_MoveElemLeft(mgui_nCursorPos+1);
01021 data_MoveElemLeft(mgui_nCursorPos+1);
01022
01023
01024 data_Check();
01025 gui_CheckCursorPos();
01026 break;
01027
01028 case mcIR_DISTRIBUTE:
01029 mcASSERT(pnewelem != NULL && *pnewelem != mcEmptyElement,
01030 wxT("No element to distribute !!"));
01031
01032 if (pnewelem->data_GetType() == mcET_BRACKET) {
01033
01034
01035
01036 bool left = ((const mcBracket *)pnewelem)->hlp()->mgui_bRemoveLeftBracket;
01037 gui_SetBracketToReplace(*pnewelem, left);
01038 }
01039 break;
01040
01041 default:
01042 mcASSERT(0, wxT("Unhandled return flag"));
01043 }
01044
01045 return mcIR_OKAY;
01046 }
01047
01048 mcInsertRes mcPolynomialHelpers::gui_Insert(const mcElement &toinsert, mcElement *)
01049 {
01050 mcCursorPos cp(data_Get(mgui_nCursorPos).gui_GetCursorPos());
01051
01052
01053
01054 mcInsertRes r = data_Get(mgui_nCursorPos).gui_Insert(toinsert, NULL);
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 return mcINSR_OKAY;
01066
01067
01068
01069
01070 return mcINSR_OKAY;
01071 }
01072
01073 void mcPolynomialHelpers::gui_SetCursorPos(const mcCursorPos &code)
01074 {
01075
01076
01077
01078 mcElementArrayHelpers::gui_SetCursorPos(code);
01079 }
01080
01081 void mcPolynomialHelpers::gui_CheckCursorPos() const
01082 {
01083
01084 if (data_GetCount() > 0) {
01085
01086
01087 mcASSERT(data_isValidElem(mgui_nCursorPos),
01088 wxT("Cursor placed on an invalid element !"));
01089 mcASSERT(mgui_nCursorPos >= 0,
01090 wxT("Cursor position undefined"));
01091 mcASSERT(mgui_nCursorPos < data_GetCount(),
01092 wxT("Cursor position is beyond upper limit"));
01093
01094 mcASSERT(!data_Get(mgui_nCursorPos).gui_GetCursorPos().isUndefined(),
01095 wxT("Cursor position undefined"));
01096
01097 } else {
01098
01099
01100 mcASSERT(mgui_nCursorPos == -1, wxT("Array is empty, wrong cursor position"));
01101 }
01102
01103
01104 if (!data_isArrayEmpty()) {
01105 mcASSERT(!data_isEmptyEntry(mgui_nCursorPos), wxT("Cursor position is wrong"));
01106 mcASSERT(!data_isOp(mgui_nCursorPos), wxT("Cursor position is wrong"));
01107 }
01108 }
01109
01110 void mcPolynomialHelpers::gui_DoSplit(mcElementType type, const mcKey &key)
01111 {
01112 mcElement ptmp = mcEmptyElement;
01113
01114 mcASSERT(type == mcET_ADDOP || type == mcET_SUBOP,
01115 wxT("The splitter elements can be only mcAddOp or mcSubOp"));
01116
01117
01118
01119 bool b = data_Get(mgui_nCursorPos).gui_Split(&ptmp);
01120 mcASSERT(!b, wxT("A monomial asked us to be deleted ?"));
01121 mcUNUSED(b);
01122
01123
01124 mcASSERT(ptmp != mcEmptyElement, wxT("Tried to split an element which does not support splitting"));
01125
01126
01127
01128 data_MoveElemRight(mgui_nCursorPos+1);
01129 data_Set(mgui_nCursorPos+1, ptmp);
01130
01131
01132 data_MoveElemRight(mgui_nCursorPos+1);
01133
01134
01135 data_AddNewOp(type, mgui_nCursorPos+1);
01136
01137
01138 mgui_nCursorPos +=2;
01139 }
01140
01141 int mcPolynomialHelpers::data_AddNewEmptyMonomial(int pos)
01142 {
01143
01144
01145
01146
01147 if (pos == -1) pos = data_GetCount();
01148
01149
01150 mcMonomial m;
01151 mcElement &box = m.data_AddNewElement(mcET_EMPTYBOX);
01152 box.data_AddProperty(mcEP_INITIALIZED);
01153
01154 data_AddElements(&m, 1, pos);
01155 data_Check();
01156
01157 return pos;
01158 }
01159
01160 void mcPolynomialHelpers::gui_AddNewEmptyMonomial(int pos)
01161 {
01162
01163
01164
01165
01166 mcKey fake(mcEmptyBoxHelpers::sgui_pNewEmptyBox->GetEvent(), TRUE);
01167 if (pos == -1) pos = data_GetCount();
01168
01169
01170 mgui_nCursorPos = gui_AddNewElement(mcET_MONOMIAL, fake, pos);
01171 }
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 wxXml2Node mcPolynomialHelpers::io_GetMathML(bool bdata_GetPresentation) const
01184 {
01185
01186
01187 if (data_GetCount() == 1) {
01188
01189
01190 return data_Get(0).io_GetMathML(bdata_GetPresentation);
01191 }
01192
01193
01194 wxXml2Node maintag;
01195 maintag.CreateTemp(wxXML_ELEMENT_NODE, wxXml2EmptyDoc, wxT("mrow"));
01196
01197
01198 for (int i=0; i < data_GetCount(); i++) {
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214 wxXml2Node node(data_Get(i).io_GetMathML(bdata_GetPresentation));
01215 maintag.AddChild(node);
01216 }
01217
01218 return maintag;
01219 }
01220
01221 wxString mcPolynomialHelpers::io_GetInlinedExpr() const
01222 {
01223 wxString str;
01224
01225
01226 for (int i=0; i < data_GetCount(); i++) {
01227
01228
01229
01230
01231 wxString tmp = data_Get(i).io_GetInlinedExpr();
01232
01233
01234 str += tmp;
01235 }
01236
01237
01238 return str;
01239 }
01240
01241 bool mcPolynomialHelpers::io_ImportPresentationMathML(wxXml2Node tag, wxString &err)
01242 {
01243 wxXml2Node p, toinsert = wxXml2EmptyNode;
01244
01245
01246
01247
01248 data_DeleteAll();
01249
01250 p = tag.GetChildren();
01251 while (p != wxXml2EmptyNode) {
01252
01253 if (p.GetType() == wxXML_ELEMENT_NODE && p.GetName() == wxT("mo")) {
01254
01255
01256
01257 toinsert = p;
01258
01259 } else if (p.GetType() == wxXML_ELEMENT_NODE && p.GetName() != wxT("mrow")) {
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269 p.Encapsulate(wxT("mrow"));
01270 }
01271
01272 if (p.GetType() == wxXML_ELEMENT_NODE && p.GetName() == wxT("mrow")) {
01273
01274
01275 mcMonomial pnew;
01276
01277
01278 if (toinsert != wxXml2EmptyNode) {
01279 p.GetChildren().AddPrevious(toinsert);
01280 toinsert = wxXml2EmptyNode;
01281 }
01282
01283
01284 if (!pnew.io_ImportPresentationMathML(p, err))
01285 return FALSE;
01286
01287
01288 data_AddElements(&pnew, 1);
01289 }
01290
01291
01292 p = p.GetNext();
01293 }
01294
01295 return TRUE;
01296 }
01297
01298 bool mcPolynomialHelpers::io_ImportInlinedExpr(const wxString &todecode, int *c,
01299 wxString &pErr, int mlimit)
01300 {
01301 wxString token(todecode);
01302 int count, n = 0;
01303
01304
01305 data_DeleteAll();
01306
01307 while (!token.IsEmpty() && (mlimit < 0 || n < mlimit))
01308 {
01309
01310 wxString str = token.GetChar(0);
01311 mcElementType newop = mcElementHelpers::io_isCharBeginChar(str);
01312 if (mcOperatorHelpers::data_isOp(newop)) {
01313
01314
01315 data_AddNewElement(newop);
01316 token.Remove(0, 1);
01317
01318 } else {
01319
01320
01321
01322
01323
01324 mcASSERT(data_isArrayEmpty(),
01325 wxT("A mcPolynomial must contain mcMonomials *always* ")
01326 wxT("interleaved with mcAddOp/mcSubOps"));
01327 }
01328
01329
01330 mcMonomial pnew;
01331 n++;
01332
01333
01334 if (!pnew.io_ImportInlinedExpr(token, &count, pErr))
01335 return FALSE;
01336
01337
01338 data_AddElements(&pnew, 1);
01339 token = token.Right(token.Len()-count);
01340 }
01341
01342
01343 if (c) *c = todecode.Len()-token.Len();
01344
01345
01346
01347 mcIOLOG(wxT("mcPolynomialHelpers::io_ImportInlinedExpr - before pruning brackets: [%s]"), mcTXTTHIS);
01348 data_ReplaceAllParentheses();
01349
01350
01351
01352 for (int i=0, max=data_GetNumOfElemType(mcET_MONOMIAL); i < max; i++) {
01353 mcMonomial &m = (mcMonomial &)data_GetElemOfType(i, mcET_MONOMIAL);
01354
01355
01356 m.data_DeleteAllElemType(mcET_PARENTHESIS);
01357 m.data_Repair();
01358 }
01359
01360 mcIOLOG(wxT("mcPolynomialHelpers::io_ImportInlinedExpr - after pruning brackets: [%s]"), mcTXTTHIS);
01361
01362
01363 io_PostProcessChildren();
01364
01365 return TRUE;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376 mcPolynomial mcPolynomialHelpers::math_GetPolynomialWrapper() const
01377 {
01378 mcPolynomial pol(this);
01379
01380
01381
01382
01383
01384 pol.data_MakePrivateCopy();
01385
01386 return pol;
01387 }
01388
01389 mcArrayEntry mcPolynomialHelpers::math_WrapMonomial(const mcMonomial &mon)
01390 {
01391
01392 data_DeleteAll();
01393
01394
01395 int midx = data_AddElements((mcElement *)(&mon), 1);
01396
01397
01398 data_Check();
01399 return mcArrayEntry(this, mcMAKEPOL_IDX(midx, 0));
01400 }
01401
01402 mcArrayEntry mcPolynomialHelpers::math_WrapSimple(const mcElement &p)
01403 {
01404
01405 if (p.data_GetType() != mcET_MONOMIAL) {
01406
01407
01408 mcMonomial m;
01409 int idx = m.data_AddElements(&p, 1);
01410
01411
01412
01413
01414 mcArrayEntry ret = math_WrapMonomial(m);
01415 ret.data_SetIdx((ret.mdata_idx << 16) | idx);
01416 return ret;
01417 }
01418
01419
01420 return math_WrapMonomial(mcMonomial(p));
01421 }
01422
01423 mcElementArray mcPolynomialHelpers::math_CreateWrapperFor(const mcElement &toembed) const
01424 {
01425 if (toembed.data_GetType() != mcET_MONOMIAL &&
01426 toembed.data_GetType() != mcET_POLYNOMIAL) {
01427
01428
01429
01430
01431 mcMonomial tmp;
01432 tmp.math_WrapSimple(toembed);
01433 return mcElementArrayHelpers::math_CreateWrapperFor(tmp);
01434 }
01435
01436 return mcElementArrayHelpers::math_CreateWrapperFor(toembed);
01437 }
01438
01439 int mcPolynomialHelpers::math_DataToMathIdx(int dataindex) const
01440 {
01441
01442 data_CheckIndex(dataindex);
01443 if (data_isOp(dataindex))
01444 return -1;
01445
01446
01447
01448
01449 return (dataindex >> 1);
01450 }
01451
01452 int mcPolynomialHelpers::math_MathToDataIdx(int mathindex) const
01453 {
01454 if (mathindex < 0 || mathindex >= math_GetCount()) {
01455
01456 mcMATHLOG(wxT("mcPolynomialHelpers::math_MathToDataIdx [%s] - ")
01457 wxT("invalid conversion required"), mcTXTTHIS);
01458 return -1;
01459 }
01460
01461
01462
01463
01464
01465
01466 return mathindex*2 + (int)(data_isOp(0));
01467 }
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 int mcPolynomialHelpers::math_GetSign(int n) const
01482 {
01483
01484 n = math_MathToDataIdx(n);
01485 mcASSERT(n != -1, wxT("Invalid index !!"));
01486
01487
01488 if (n == 0) return 1;
01489 mcASSERT(data_isAddSubOp(n-1),
01490 wxT("A polynomial must contain monomials always separated by mcAddOp or mcSubOp"));
01491
01492 return (data_Get(n-1).data_GetType() == mcET_ADDOP) ? 1 : -1;
01493 }
01494
01495 void mcPolynomialHelpers::math_SetSign(int n, int sgn)
01496 {
01497 int i = math_MathToDataIdx(n);
01498
01499 if (i > 0) {
01500
01501
01502
01503 mcASSERT(data_isOp(i-1), wxT("A monomial should always be preceded by an op"));
01504
01505
01506 data_AddNewOp(((sgn < 0) ? mcET_SUBOP : mcET_ADDOP), i-1);
01507
01508 } else {
01509
01510 if (sgn < 0) {
01511
01512
01513 data_MoveElemRight(0);
01514 data_AddNewOp(mcET_SUBOP, 0);
01515
01516
01517 } else {
01518
01519
01520
01521 }
01522 }
01523 }
01524 bool mcPolynomialHelpers::math_DeleteFirstOp()
01525 {
01526 if (data_isArrayEmpty() ||
01527 !data_isOp(0))
01528 return FALSE;
01529
01530 if (data_isOp(0) &&
01531 data_Get(0).data_GetType() != math_GetNeutralOpType())
01532 return FALSE;
01533
01534
01535 data_Delete(0);
01536 data_MoveElemLeft(0);
01537 return TRUE;
01538 }
01539
01540 mcExpSimRes mcPolynomialHelpers::math_Reorder()
01541 {
01542 mcMATHLOG(wxT("mcPolynomialHelpers::math_Reorder - going to reorder [%s]"), mcTXTTHIS);
01543
01544
01545
01546
01547 data_CreateFirstOp();
01548 int n = math_ReorderElements(data_GetArray(), data_GetCount(), 1, 2);
01549 data_Check();
01550
01551
01552 math_DeleteFirstOp();
01553 mcMATHLOG(wxT("mcPolynomialHelpers::math_Reorder - result is [%s]"), mcTXTTHIS);
01554
01555
01556 return (n == 0 ? mcESR_DONE : mcESR_NOTFINISHED);
01557 }
01558
01559 void mcPolynomialHelpers::math_ChangeAllSigns()
01560 {
01561 for (int i=0; i < math_GetCount(); i++)
01562 math_ChangeSign(i);
01563 }
01564
01565 void mcPolynomialHelpers::math_SyncCoeffWithSigns()
01566 {
01567
01568 for (int i=0,max=math_GetCount(); i < max; i++) {
01569
01570 mcRealValue coeff = math_Get(i).math_GetCoeff();
01571
01572 if (coeff < 0) {
01573
01574
01575
01576
01577 math_SetSign(i, -1);
01578
01579
01580 mcMATHLOG(wxT("mcPolynomialHelpers::math_SyncCoeffWithSigns - I set ")
01581 wxT("the sign of the [%s] monomial (which has coeff [%s]) to NEGATIVE"),
01582 mcTXT(math_Get(i)), mcTXTV(coeff));
01583
01584 } else if (coeff > 0) {
01585
01586
01587 math_SetSign(i, +1);
01588
01589 mcMATHLOG(wxT("mcPolynomialHelpers::math_SyncCoeffWithSigns - I set ")
01590 wxT("the sign of the [%s] monomial (which has coeff [%s]) to POSITIVE"),
01591 mcTXT(math_Get(i)), mcTXTV(coeff));
01592
01593 } else {
01594
01595
01596
01597 }
01598 }
01599 }
01600
01601 const mcNumber &mcPolynomialHelpers::math_GetNumSign(const mcMonomial &tofind, int n) const
01602 {
01603 int pos = math_NonRecursiveFindInChildren(n, tofind.hlp());
01604 if (pos < 0) return mcEmptyNumber;
01605
01606
01607 int sign = math_GetSign(pos);
01608 return (sign == 1 ? *mcNumberHelpers::smath_pOne : *mcNumberHelpers::smath_pMinusOne);
01609 }
01610
01611 void mcPolynomialHelpers::math_PackSign(mcMonomial &m, int occ) const
01612 {
01613 #ifdef EXTENDED_COEFF
01614 mcMonomial num = m.math_GetCoeff();
01615 #else
01616 mcNumber num = m.math_GetCoeff();
01617 #endif
01618 mcNumber mult = math_GetNumSign(m, occ);
01619 mcASSERT(mult != mcEmptyElement, wxT("We could not find 'm'"));
01620
01621 num.math_SimpleMultiplyBy(mult);
01622 m.math_SetCoeff(num);
01623 }
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 int mcPolynomialHelpers::math_FindMonomialContaining(const mcElement &elem,
01634 int occ, int *res) const
01635 {
01636 int n = -1;
01637 for (int i=0,max=math_GetCount(); i < max; i++) {
01638
01639
01640 n = math_Get(i).math_GetIndexOf(occ, elem);
01641 if (n != -1) {
01642
01643
01644 if (res) *res = n;
01645 return i;
01646 }
01647 }
01648
01649
01650 return -1;
01651 }
01652
01653 const mcMonomial &mcPolynomialHelpers::math_GetMonomialContaining(const mcElement &elem,
01654 int occ, int *res) const
01655 {
01656 int idx = math_FindMonomialContaining(elem, occ, res);
01657
01658 if (idx != -1)
01659 return math_Get(idx);
01660 return mcEmptyMonomial;
01661 }
01662
01663 mcMonomial mcPolynomialHelpers::math_GetCoeffOf(int mathidx, const mcElement *toremove,
01664 int ntoremove) const
01665 {
01666
01667 mcMonomial res = math_Get(mathidx);
01668
01669
01670 for (int i=0; i < ntoremove; i++)
01671 res.math_Delete(0, toremove[i], FALSE);
01672
01673
01674 if (math_GetSign(mathidx) == -1) math_PackSign(res);
01675
01676 return res;
01677 }
01678
01679 mcMonomial mcPolynomialHelpers::math_GetCoeffOf(const mcSymbolProperties *sym,
01680 const mcPolynomial &exp, int occ) const
01681 {
01682 mcMATHLOG(wxT("mcPolynomialHelpers::math_GetCoeffOf [%s] - searching [%s]^[%s]"),
01683 mcTXTTHIS, mcTXTP(sym), mcTXT(exp));
01684
01685
01686
01687 mcSymbol s(sym->data_GetSafeLinkedSym());
01688
01689 if (exp.math_isWrappingOnly(0.0)) {
01690
01691 int n = -1;
01692
01693
01694 for (int i=0; i < math_GetCount(); i++) {
01695 if (!math_Get(i).math_Contains(s)) {
01696
01697 n++;
01698
01699
01700
01701 if (n == occ) return mcMonomial(math_Get(i));
01702 }
01703 }
01704
01705 return mcEmptyMonomial;
01706 }
01707
01708 s.math_SetExp(exp);
01709
01710
01711 int n = -1;
01712 const mcMonomial &res = math_GetMonomialContaining(s, occ, &n);
01713 if (res == mcEmptyMonomial) return mcEmptyMonomial;
01714
01715
01716 mcMonomial m(res);
01717
01718
01719
01720
01721
01722
01723 m.math_Remove(n, FALSE);
01724
01725
01726
01727
01728 return m;
01729 }
01730
01731 mcMonomial mcPolynomialHelpers::math_GetCoeffOf(const mcSymbolProperties *sym,
01732 const mcRealValue &exp, int occ) const
01733 {
01734 mcPolynomial tmp;
01735 tmp.math_WrapNumber(exp);
01736
01737
01738 mcMonomial ret = math_GetCoeffOf(sym, tmp, occ);
01739
01740
01741 return ret;
01742 }
01743
01744 mcIntegerValue mcPolynomialHelpers::math_GetMaxDegreeFor(const mcSymbolProperties *sym) const
01745 {
01746 mcIntegerValue max = 0;
01747
01748 for (int i=0; i < math_GetCount(); i++) {
01749
01750
01751 mcIntegerValue d = math_Get(i).math_GetMaxDegreeFor(sym);
01752 if (!d.isValid()) return *mcIntegerValue::pNAN;
01753
01754
01755 max = max.GetMax(d);
01756 }
01757
01758 mcASSERT(max.isValid(), wxT("Something really wrong"));
01759 return max;
01760 }
01761
01762 mcExpSimRes mcPolynomialHelpers::math_SimplifySolveOp(long flags)
01763 {
01764 bool stilltowork = FALSE;
01765
01766 mcMATHLOG(wxT("mcPolynomialHelpers::math_SimplifySolveOp"));
01767
01768
01769 for (int i=0; i < math_GetCount(); i++) {
01770
01771
01772 mcMonomial &left = math_Get(i);
01773 mcOperator &lp = math_GetOpPreceding(i);
01774
01775 for (int j=0; j < math_GetCount(); j++) {
01776
01777
01778 mcMonomial &right = math_Get(j);
01779 if (i == j) continue;
01780
01781
01782 mcOperator &rp = math_GetOpPreceding(j);
01783 if (rp == mcEmptyElement) continue;
01784 mcMATHLOG(wxT("mcPolynomialHelpers::math_SimplifySolveOp - I'm trying to apply ")
01785 wxT("the op [%s] between the [%s] and [%s] elements"),
01786 mcTXT(rp), mcTXT(left), mcTXT(right));
01787
01788
01789 mcElement rep = mcEmptyElement;
01790 mcBasicOpRes res;
01791 int sign=1;
01792
01793 if (lp.data_GetType() == rp.data_GetType()) {
01794
01795 mcOperator *op = (mcOperator *)mcElementHelpers::data_GetInstanceOf(mcET_ADDOP);
01796 res = op->math_Apply(left, right, &rep);
01797 if (res == mcBOR_INVALID)
01798 continue;
01799
01800 } else {
01801
01802 mcOperator *op = (mcOperator *)mcElementHelpers::data_GetInstanceOf(mcET_SUBOP);
01803 res = op->math_Apply(left, right, &rep);
01804 if (lp.data_GetType() == mcET_SUBOP)
01805 sign=-1;
01806 if (res == mcBOR_INVALID)
01807 continue;
01808
01809
01810
01811
01812
01813 if (left.math_GetCoeff() < 0) {
01814 math_SetSign(i, -1*sign);
01815 math_Get(i).math_Abs();
01816 } else {
01817 math_SetSign(i, 1*sign);
01818 }
01819 }
01820
01821
01822 stilltowork = TRUE;
01823 mcMATHLOG(wxT("mcPolynomialHelpers::math_SimplifySolveOp - applied ")
01824 wxT("the op [%s] between the [%s] and [%s] elements"),
01825 mcTXT(rp), mcTXT(left), mcTXT(right));
01826
01827
01828 math_HandleBasicOpRes(res, rep, j);
01829 }
01830 }
01831
01832 if (stilltowork)
01833 return mcESR_NOTFINISHED;
01834 return mcESR_DONE;
01835
01836 }
01837
01838 mcExpSimRes mcPolynomialHelpers::math_Simplify(long flags, mcElement *newelem)
01839 {
01840 mcLOG(wxT("mcPolynomialHelpers::math_Simplify"));
01841
01842
01843 mcExpSimRes r = mcElementArrayHelpers::math_Simplify(flags, newelem);
01844 math_DeleteFirstOp();
01845 if (r != mcESR_DONE) return r;
01846
01847
01848
01849
01850
01851
01852
01853
01854 return mcESR_DONE;
01855 }
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 mcBasicOpRes mcPolynomialHelpers::math_Add(const mcElement &e, mcElement *pp, bool add)
01866 {
01867 mcMATHLOG(wxT("mcPolynomialHelpers::math_Add [%s] - I'm %s [%s]"), mcTXTTHIS,
01868 (add == TRUE ? wxT("adding") : wxT("subtracting")), mcTXT(e));
01869 mcPolynomial p(e);
01870
01871 if (p.data_isArrayEmpty())
01872 return mcBOR_REMOVE_OPERAND;
01873
01874 if (add) {
01875
01876
01877
01878 if (!this->data_isArrayEmpty() &&
01879 !p.data_isOp(0)) {
01880
01881 data_AddNewOp(mcET_ADDOP);
01882 }
01883
01884
01885 data_Merge(p);
01886
01887 } else {
01888
01889 mcPolynomial p2(p);
01890
01891
01892 p2.math_ChangeAllSigns();
01893 mcMATHLOG(wxT("[%s]"), mcTXT(p2));
01894 math_SimpleAdd(p2);
01895 }
01896
01897 data_Check();
01898
01899 return mcBOR_REMOVE_OPERAND;
01900 }
01901
01902 mcBasicOpRes mcPolynomialHelpers::math_MultiplyBy(const mcElement &e, mcElement *pp)
01903 {
01904 if (data_isArrayEmpty())
01905 return mcBOR_REMOVE_OPERAND;
01906
01907 mcPolynomial p(e);
01908 mcPolynomial pnew = mcEmptyElement;
01909
01910
01911
01912 if (math_GetCount() > 1 || math_GetSign(0) == -1) {
01913
01914
01915 mcElementArrayHelpers::math_EmbedInBracket();
01916 }
01917
01918
01919
01920 if (p.math_GetCount() > 1) {
01921
01922
01923 pnew = p;
01924 p = pnew;
01925
01926
01927 p.math_EmbedInBracket();
01928
01929 }
01930
01931
01932 mcASSERT(p.math_GetCount() == 1, wxT("Something wrong"));
01933 mcASSERT(this->math_GetCount() == 1, wxT("Something wrong"));
01934
01935
01936 mcBasicOpRes r = math_Get(0).math_MultiplyBy(p.math_Get(0), pp);
01937
01938
01939
01940
01941
01942 data_Check();
01943
01944
01945 switch (r) {
01946 case mcBOR_INVALID:
01947 case mcBOR_REPLACE_OPERAND:
01948 case mcBOR_REPLACE_BOTH:
01949 mcASSERT(0, wxT("Two monomials which cannot be multiplied ?"));
01950
01951 case mcBOR_REMOVE_OPERAND:
01952 return mcBOR_REMOVE_OPERAND;
01953
01954 default:
01955 mcASSERT(0, wxT("TODO"));
01956 }
01957
01958 return mcBOR_REMOVE_OPERAND;
01959 }
01960
01961 mcBasicOpRes mcPolynomialHelpers::math_DivideBy(const mcElement &pol, mcElement *pp)
01962 {
01963 if (data_isArrayEmpty())
01964 return mcBOR_REMOVE_OPERAND;
01965
01966
01967
01968 mcASSERT(pol.data_GetType() == mcET_POLYNOMIAL, wxT("see math_DivideBy() description..."));
01969 math_EmbedInFraction().data_GetFraction().data_SetDen(pol);
01970
01971 mcMATHLOG(wxT("mcPolynomialHelpers::math_DivideBy - dividing by [%s], result is [%s]"),
01972 mcTXT(pol), mcTXTTHIS);
01973
01974 return mcBOR_REMOVE_OPERAND;
01975 }
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000 void mcPolynomialHelpers::math_DeleteSelection()
02001 {
02002
02003 gui_DeleteSelection();
02004 data_Check();
02005 }
02006
02007 mcIntegerValue mcPolynomialHelpers::math_RaiseGetCoeff(int *indexes, int m)
02008 {
02009 mcIntegerValue res = 1;
02010
02011
02012
02013
02014
02015
02016
02017 for (int x=0; x < m; x++)
02018 res *= mcIntegerValue::GetComb(indexes[x], indexes[x+1]);
02019
02020 return res;
02021 }
02022
02023 bool mcPolynomialHelpers::math_CanBeRaisedTo(const mcPolynomial &pol) const
02024 {
02025 int count = math_GetCount();
02026
02027
02028
02029 if (count == 0 || count == 1)
02030 return TRUE;
02031
02032
02033
02034 if (!pol.math_isWrappingNumOnly())
02035 return FALSE;
02036
02037 mcRealValue r(pol.math_GetWrappedNumber());
02038
02039 if (r.isInteger())
02040 return TRUE;
02041 return FALSE;
02042 }
02043
02044 void mcPolynomialHelpers::math_RaiseTo(const mcRealValue &r)
02045 {
02046 mcMATHLOG(wxT("mcPolynomialHelpers::math_RaiseChildrenTo [%s] - raising to [%s]"),
02047 mcTXTTHIS, mcTXTV(r));
02048 mcIntegerValue n = r;
02049
02050
02051 if (math_GetCount() == 0)
02052 return;
02053
02054 if (math_GetCount() == 1) {
02055
02056
02057
02058 math_Get(0).math_RaiseTo(r);
02059 return;
02060 }
02061
02062
02063 if (!r.isInteger()) {
02064
02065
02066
02067
02068
02069
02070 math_EmbedInBracketAndRaiseTo(r);
02071 return;
02072
02073 } else if (n == 1) {
02074
02075
02076
02077 return;
02078 }
02079
02080 mcMATHLOG(wxT("mcPolynomialHelpers::math_RaiseTo - raising %d monomials to %s"),
02081 math_GetCount(), n.GetStr().c_str());
02082 int x, m = math_GetCount(), *indexes = new int[m+2];
02083
02084
02085
02086
02087 indexes[0] = n.GetInt();
02088 for (x=1; x < m+2; x++)
02089 indexes[x] = 0;
02090
02091 mcPolynomial res;
02092 bool exit = FALSE;
02093 int level = 1;
02094 while (!exit) {
02095
02096 mcMonomial mx;
02097
02098
02099 int sign = 1;
02100
02101
02102
02103
02104 mcIntegerValue coeff = math_RaiseGetCoeff(indexes, m);
02105 mx.math_WrapNumber(coeff);
02106 mcMATHLOG(wxT("mcPolynomialHelpers::math_RaiseTo - the coeff of the %d-th monomial is %s"),
02107 res.math_GetCount(), coeff.GetStr().c_str());
02108 for (int y=0; y < m; y++) {
02109
02110
02111 mcMonomial tmp(math_Get(y));
02112
02113
02114 int exp = indexes[y]-indexes[y+1];
02115
02116
02117 if (exp != 0) {
02118
02119
02120 if (exp != 1) tmp.math_RaiseTo(mcPolynomial(exp));
02121 sign *= (int)pow(math_GetSign(y), exp);
02122
02123
02124 mx.math_MultiplyBy(tmp, NULL);
02125 }
02126 }
02127
02128 res.math_SimpleAdd(mx, (sign == 1 ? TRUE : FALSE));
02129
02130
02131 if (level < m) {
02132
02133
02134 indexes[level]++;
02135 if (level+1 < m || indexes[level] == indexes[level-1])
02136 level++;
02137
02138 } else if (level == m) {
02139
02140
02141 level--;
02142 bool startcycle = FALSE;
02143 while (indexes[level-1] <= indexes[level]) {
02144 indexes[level] = 0;
02145 level--;
02146 startcycle = TRUE;
02147
02148 if (level == 0) {
02149
02150
02151
02152
02153 exit = TRUE;
02154 break;
02155 }
02156 }
02157
02158
02159 if (startcycle) {
02160 indexes[level]++;
02161 level++;
02162 }
02163 }
02164 }
02165
02166 delete indexes;
02167 data_DeepCopy(res.chlp());
02168 }
02169
02170 mcBasicOpRes mcPolynomialHelpers::math_RaiseTo(const mcPolynomial &p)
02171 {
02172 if (math_CanBeRaisedTo(p)) {
02173
02174 if (math_GetCount() == 0)
02175 return mcBOR_REMOVE_OPERAND;
02176
02177 if (math_GetCount() == 1)
02178 return math_Get(0).math_RaiseTo(p);
02179
02180
02181
02182 math_RaiseTo(p.math_GetWrappedNumber());
02183 return mcBOR_REMOVE_OPERAND;
02184 }
02185
02186
02187 math_EmbedInBracketAndRaiseTo(p);
02188 return mcBOR_REMOVE_OPERAND;
02189 }
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233 void mcPolynomialHelpers::math_Factorize(int *n, int count)
02234 {
02235
02236 }
02237
02238 mcMonomial mcPolynomialHelpers::math_GetGCDFor(int *n, int count) const
02239 {
02240 mcMonomial gcd(mcEmptyElement);
02241 bool all = FALSE;
02242
02243 if (math_GetCount() == 0)
02244 return mcEmptyElement;
02245
02246 if (count==-1) {
02247
02248
02249 count = math_GetCount();
02250 all = TRUE;
02251
02252
02253 gcd = math_Get(0);
02254
02255 } else {
02256
02257
02258 mcASSERT(count >= 1, wxT("Invalid count of elements"));
02259 gcd = math_Get(n[0]);
02260 }
02261
02262 for (int i=1; i<count; i++) {
02263
02264 mcMonomial m(mcEmptyElement);
02265 if (all)
02266 m = math_Get(i);
02267 else
02268 m = math_Get(n[i]);
02269
02270
02271
02272 gcd = gcd.math_GetGCD(m);
02273 }
02274
02275 return gcd;
02276 }
02277
02278 void mcPolynomialHelpers::math_FactoreOut(int *n, int count, bool bForceUseless)
02279 {
02280
02281 if (math_GetCount() <= 1) return;
02282
02283
02284
02285 mcMonomial gcd(math_GetGCDFor(n, count));
02286 bool gcdisone = gcd.math_isWrappingOnly(1.0);
02287 if (gcdisone && !bForceUseless)
02288 return;
02289 mcMATHLOG(wxT("mcPolynomialHelpers::math_FactoreOut - the GCD ")
02290 wxT("among all my monomials is [%s]"), mcTXT(gcd));
02291
02292
02293
02294
02295
02296
02297
02298
02299 mcArrayEntry br = math_EmbedInBracket(n, count);
02300 mcPolynomial &contents = br.data_GetBracket().data_GetContent();
02301
02302 if (gcdisone || contents.math_GetCount() <= 1)
02303 return;
02304
02305
02306 for (int j=0,max=contents.math_GetCount(); j<max; j++)
02307 contents.math_Get(j).math_SimpleDivideBy(gcd);
02308
02309
02310
02311 mcMonomial &m = (mcMonomial &)math_GetMonomialContaining(br.data_GetRef());
02312 m.math_SimpleMultiplyBy(gcd);
02313
02314 data_Check();
02315 }
02316
02317 void mcPolynomialHelpers::math_FactoreOut(const mcSymbolProperties *unk,
02318 const mcPolynomial &pol,
02319 bool bForceUseless)
02320 {
02321
02322 if (math_GetCount() <= 1) return;
02323
02324
02325
02326 int *arr = new int[math_GetCount()];
02327 int count=0;
02328
02329
02330
02331 for (int i=0,max=math_GetCount(); i < max; i++)
02332 if (math_Get(i).math_ContainsSymbol(unk, pol))
02333 arr[count++] = i;
02334
02335
02336 if (count == 0) {
02337 delete [] arr;
02338 return;
02339 }
02340
02341 math_FactoreOut(arr, count, bForceUseless);
02342 delete [] arr;
02343 }
02344
02345 void mcPolynomialHelpers::math_FactoreOutFreeOf(const mcSymbolProperties *unk,
02346 const mcPolynomial &pol,
02347 bool bForceUseless)
02348 {
02349
02350 if (math_GetCount() <= 1) return;
02351
02352
02353
02354 int *arr = new int[math_GetCount()];
02355 int count=0;
02356
02357
02358
02359 for (int i=0,max=math_GetCount(); i < max; i++)
02360 if (!math_Get(i).math_ContainsSymbol(unk, pol))
02361 arr[count++] = i;
02362
02363
02364 if (count == 0) {
02365 delete [] arr;
02366 return;
02367 }
02368
02369 math_FactoreOut(arr, count, bForceUseless);
02370 delete [] arr;
02371 }
02372
02373 void mcPolynomialHelpers::math_FactoreOut(const mcSymbolArray *arr)
02374 {
02375
02376 for (int i=0; i < arr->data_GetCount(); i++)
02377 math_FactoreOut(arr->data_GetSymbol(i), mcEmptyPolynomial, FALSE);
02378 }
02379
02380 void mcPolynomialHelpers::math_FactoreOutConstants()
02381 { math_FactoreOut(&mcSymbol::arrConstants); }
02382
02383 void mcPolynomialHelpers::math_FactoreOutUnknowns()
02384 { math_FactoreOut(&mcSymbol::arrUnknowns); }
02385
02386 void mcPolynomialHelpers::math_FactoreOutParameters()
02387 { math_FactoreOut(&mcSymbol::arrParameters); }
02388
02389 mcExpSimRes mcPolynomialHelpers::math_HandleExpSimFlag(mcExpSimRes r, mcElement *pnew, int i)
02390 {
02391
02392 if (r == mcESR_DISTRIBUTE) {
02393
02394 mcMonomial &m = (mcMonomial &)data_Get(i);
02395 int pnewidx = m.data_GetIndexOf(*pnew);
02396
02397
02398
02399 if (pnew->data_GetType() == mcET_BRACKET)
02400 math_DistributeBracket(i, pnewidx);
02401 else {
02402
02403
02404
02405 mcASSERT(0, wxT("Unhandled case..."));
02406 }
02407
02408 return mcESR_NOTFINISHED;
02409 }
02410
02411
02412 if (r == mcESR_CHANGE_SIGN) {
02413
02414 math_ChangeSign(math_DataToMathIdx(i));
02415 return mcESR_NOTFINISHED;
02416 }
02417
02418 return mcElementArrayHelpers::math_HandleExpSimFlag(r, pnew, i);
02419 }
02420
02421 void mcPolynomialHelpers::math_DistributeBracket(int mdataidx, int bridx)
02422 {
02423 mcASSERT(data_Get(mdataidx).data_GetType() == mcET_MONOMIAL,
02424 wxT("the first parameter is the data index of the monomial with the bracket to expand"));
02425 int signbeforebr = 1;
02426
02427
02428 mcMonomial m = data_Detach(mdataidx);
02429 data_MoveElemLeft(mdataidx);
02430 mcASSERT(m.data_GetElemIndexOfType(0, mcET_BRACKET) == m.math_MathToDataIdx(bridx),
02431 wxT("the given monomial should contain the bracket to expand at the given math idx"));
02432
02433
02434 mcBracket br = m.math_Get(bridx);
02435 mcPolynomial brcontents = br.data_GetContent();
02436 mcMATHLOG(wxT("mcPolynomialHelpers::math_DistributeBracket - the bracket's contents are [%s]"), mcTXT(brcontents));
02437
02438
02439 if (mdataidx > 0 && data_isAddSubOp(mdataidx-1)) {
02440 signbeforebr = (data_Get(mdataidx-1).data_GetType() == mcET_ADDOP) ? 1 : -1;
02441 data_MoveElemLeft(mdataidx-1);
02442 mdataidx--;
02443 }
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459 int pnewcount = brcontents.math_GetCount();
02460 int mcount = m.math_GetCount();
02461 for (int n=0; n < pnewcount; n++) {
02462
02463
02464 mcMonomial newm;
02465 newm.math_ResetToOne();
02466 int add = 1;
02467
02468
02469 for (int i=0; i < mcount; i++) {
02470
02471 mcElement tomult = m.data_Get(i);
02472 if (tomult == br) {
02473
02474
02475
02476 tomult = brcontents.math_Get(n);
02477
02478
02479 add = brcontents.math_GetSign(n);
02480
02481
02482 newm.math_SimpleMultiplyBy(tomult);
02483
02484 } else {
02485
02486
02487
02488 newm.math_SimpleMultiplyBy(tomult);
02489 }
02490 }
02491
02492
02493 newm.data_Check();
02494
02495
02496
02497 mcElementType t = (add*signbeforebr == 1) ? mcET_ADDOP : mcET_SUBOP;
02498 data_MoveElemRight(mdataidx);
02499 data_Set(mdataidx, mcElementHelpers::data_NewElem(t));
02500 data_MoveElemRight(mdataidx+1);
02501 data_Set(mdataidx+1, newm);
02502 mdataidx+=2;
02503 }
02504
02505
02506 data_Check();
02507
02508 mcMATHLOG(wxT("mcPolynomialHelpers::math_DistributeBracket - result is [%s]"), mcTXTTHIS);
02509 }
02510
02511 mcMonomial mcPolynomialHelpers::math_GetGCD(const mcElement &p) const
02512 {
02513 mcPolynomial arr(p);
02514
02515
02516 if (math_isFactorized() && arr.math_isFactorized())
02517 return math_Get(0).hlp()->math_GetGCD(arr.math_Get(0));
02518
02519
02520
02521
02522 return math_GetGCDFor(NULL, -1);
02523 }
02524
02525 mcMonomial mcPolynomialHelpers::math_GetLCM(const mcElement &p) const
02526 {
02527 mcPolynomial arr(p);
02528
02529
02530 if (math_isFactorized() && arr.math_isFactorized())
02531 return math_Get(0).hlp()->math_GetLCM(arr.math_Get(0));
02532
02533
02534
02535
02536 mcBracket br1(mcPolynomial(this).math_EmbedInBracket().data_GetRef());
02537 mcBracket br2(arr.math_EmbedInBracket().data_GetRef());
02538
02539 mcMonomial res;
02540 res.data_AddElements(&br1, 1);
02541 res.math_SimpleMultiplyBy(br2);
02542
02543 return res;
02544 }
02545
02546
02547
02548 mcArrayEntry mcPolynomialHelpers::math_EmbedInBracket(int *n, int count)
02549 {
02550 if (count == -1)
02551 return mcElementArrayHelpers::math_EmbedInBracket();
02552
02553 mcPolynomial pol;
02554 mcBracket br;
02555
02556
02557 for (int i=0; i < count; i++) {
02558
02559
02560 bool add = (math_GetSign(n[i]) == 1) ? TRUE : FALSE;
02561 pol.math_SimpleAdd(math_Get(n[i]), add);
02562
02563
02564
02565 math_Remove(n[i]);
02566 for (int j=i+1; j < count; j++)
02567 n[j]--;
02568 }
02569
02570
02571
02572 br.data_SetContent(pol);
02573
02574
02575 math_SimpleAdd(br);
02576
02577 mcArrayEntry ourb(this, mcMAKEPOL_IDX(data_GetCount()-1, 0));
02578 mcASSERT(ourb.data_GetRef().data_GetType() == mcET_BRACKET, wxT("What is this ?!?!?"));
02579
02580 return ourb;
02581 }
02582
02583 mcArrayEntry mcPolynomialHelpers::math_GetIndexOf(int occ, const mcMonomial &tofind,
02584 bool positivesign) const
02585 {
02586
02587 for (int i=0,max=math_GetCount(); i<max; i++) {
02588
02589
02590
02591 if (math_Get(i).math_Compare(tofind, TRUE) &&
02592 positivesign == (math_GetSign(0) != 0)) {
02593
02594 occ--;
02595 if (occ == -1)
02596 return mcArrayEntry(this, mcMAKEPOL_IDX(math_MathToDataIdx(i), 0));
02597
02598
02599 }
02600 }
02601
02602 return mcEmptyArrayEntry;
02603 }