00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00031
00032
00033
00034
00035 #ifdef __GNUG__
00036 #pragma implementation "Fraction.cpp"
00037 #endif
00038
00039
00040 #include "mc/mcprec.h"
00041 #ifdef __BORLANDC__
00042 #pragma hdrstop
00043 #endif
00044
00045 #ifndef mcPRECOMP
00046 #include "mc/MathCore.h"
00047 #include "mc/Fraction.h"
00048 #include "mc/Monomial.h"
00049 #include "mc/Number.h"
00050 #include "mc/Bracket.h"
00051 #endif
00052
00053
00054
00055 mcIMPLEMENT_MAIN_CLASS(mcFraction, mcElement);
00056
00057
00058
00059
00060 int mcFractionHelpers::sgui_nSpaceAboveBelow = 2;
00061 int mcFractionHelpers::sgui_nSpaceBetween = 1;
00062 int mcFractionHelpers::sgui_nAdditionalWidth = 4;
00063 int mcFractionHelpers::sgui_nAdditionalSpace = 8;
00064
00065
00066
00067
00068
00069 mcKey *mcFractionHelpers::sgui_pNewFraction = NULL;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 void mcFractionHelpers::data_AddElements(bool bNum, mcElement *p, int num, int pos,
00080 bool bOverwrite, bool bForceCopy)
00081 {
00082
00083 if (bNum)
00084 data_GetNum().data_AddElements(p, num, pos, bOverwrite, bForceCopy);
00085 else
00086 data_GetDen().data_AddElements(p, num, pos, bOverwrite, bForceCopy);
00087 }
00088
00089 #ifdef __MCDEBUG__
00090
00091 wxString mcFractionHelpers::data_Debug(long flags) const
00092 {
00093 int step = mcMathCore::Get()->m_nIndentationStep;
00094 return wxString::Format(
00095 wxT("mcFraction [\n")
00096 wxT("---->>>>>>>>>>>>>>>>>> NUMERATOR <<<<<<<<<<<<<<<<----\n")
00097 wxT("%s")
00098 wxT("---->>>>>>>>>>>>>>>>> DENOMINATOR <<<<<<<<<<<<<<<----\n")
00099 wxT("%s")
00100 wxT("mcFraction ]"),
00101 data_GetNum().data_GetDebug(step, flags).c_str(),
00102 data_GetDen().data_GetDebug(step, flags).c_str());
00103 }
00104
00105 void mcFractionHelpers::data_Check() const
00106 {
00107
00108 mcElementHelpers::data_Check();
00109
00110
00111
00112 mcASSERT(data_GetNum().data_GetCount() > 0, wxT("An empty numerator ?"));
00113 mcASSERT(data_GetDen().data_GetCount() > 0, wxT("An empty denominator ?"));
00114 }
00115
00116 #endif
00117
00118
00119
00120
00121
00122
00123
00124
00125 bool mcFractionHelpers::gui_isBeginKey(const mcKey &key) const
00126 {
00127 if (key.MatchKey(*sgui_pNewFraction))
00128 return TRUE;
00129 return FALSE;
00130 }
00131
00132 bool mcFractionHelpers::gui_isEndKey(const mcKey &ev) const
00133 {
00134 switch (mgui_nCursorPos) {
00135 case mcFRACTION_LEFTMOST:
00136 case mcFRACTION_RIGHTMOST:
00137 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(ev) ||
00138 mcMathCore::Get()->m_pCancelKey->MatchKey(ev))
00139 return FALSE;
00140 return TRUE;
00141
00142 case mcFRACTION_INSIDENUM:
00143 return data_GetNum().gui_isEndKey(ev);
00144
00145 case mcFRACTION_INSIDEDEN:
00146 return data_GetDen().gui_isEndKey(ev);
00147 }
00148
00149 mcASSERT(0, wxT("Un-handled cursor position"));
00150 return FALSE;
00151 }
00152
00153 int mcFractionHelpers::gui_GetYAnchor() const
00154 {
00155 return data_GetNum().gui_GetHeight()+
00156 sgui_nSpaceAboveBelow+sgui_nSpaceBetween+
00157 mcElementHelpers::gui_GetThickness(NULL)/2;
00158 }
00159
00160 void mcFractionHelpers::gui_DoRecalcSize()
00161 {
00162
00163 mgui_sz.SetWidth(mcMAX(data_GetNum().gui_GetWidth(),
00164 data_GetDen().gui_GetWidth()) +
00165 sgui_nAdditionalWidth + sgui_nAdditionalSpace);
00166
00167 mgui_sz.SetHeight(data_GetNum().gui_GetHeight() +
00168 data_GetDen().gui_GetHeight() +
00169 sgui_nSpaceAboveBelow * 2 +
00170 sgui_nSpaceBetween*2 +
00171 mcElementHelpers::gui_GetThickness(NULL));
00172 }
00173
00174 wxPoint mcFractionHelpers::gui_GetNumPos() const
00175 {
00176
00177
00178 return wxPoint((gui_GetWidth()-data_GetNum().gui_GetWidth())/2, sgui_nSpaceAboveBelow);
00179 }
00180
00181 wxPoint mcFractionHelpers::gui_GetDenPos() const
00182 {
00183
00184
00185 return wxPoint((gui_GetWidth()-data_GetDen().gui_GetWidth())/2,
00186 data_GetNum().gui_GetHeight() + sgui_nSpaceBetween*2 +
00187 mcElementHelpers::gui_GetThickness(NULL) + sgui_nSpaceAboveBelow);
00188 }
00189
00190 void mcFractionHelpers::gui_OnSelect(wxDC &dc, wxRect &rc)
00191 {
00192 bool existselection = FALSE;
00193
00194
00195 wxRect num(gui_GetNumPos(), data_GetNum().gui_GetSize());
00196 wxRect den(gui_GetDenPos(), data_GetDen().gui_GetSize());
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 gui_DeSelect();
00209
00210
00211 existselection = FALSE;
00212
00213
00214
00215 bool n = num.Intersects(rc), d = den.Intersects(rc);
00216
00217 if ((n && d) || existselection) {
00218
00219
00220
00221 gui_SelectAll();
00222
00223 } else if (n) {
00224
00225
00226
00227
00228 data_GetNum().gui_OnSelect(dc, rc);
00229
00230 if (data_GetNum().gui_isSelected())
00231 gui_Select();
00232
00233 } else if (d) {
00234
00235 data_GetDen().gui_OnSelect(dc, rc);
00236
00237 if (data_GetDen().gui_isSelected())
00238 gui_Select();
00239 }
00240 }
00241
00242 int mcFractionHelpers::gui_Draw(wxDC &hDC, int x, int y, long flags, const wxPoint &pt) const
00243 {
00244 wxPoint n = gui_GetNumPos(), d = gui_GetDenPos(), ptn, ptd;
00245 wxRect num(n, data_GetNum().gui_GetSize());
00246 wxRect den(d, data_GetDen().gui_GetSize());
00247 int f=0, numid, denid;
00248 long fn=flags, fd=flags;
00249
00250
00251 num.x += x;
00252 num.y += y;
00253 den.x += x;
00254 den.y += y;
00255
00256
00257
00258
00259 if (this->gui_isAllSelected()) {
00260
00261 fn &= ~mcDRW_ALLOW_TOTAL_SELECTION;
00262 fd &= ~mcDRW_ALLOW_TOTAL_SELECTION;
00263
00264 } else {
00265
00266 fn |= mcDRW_ALLOW_TOTAL_SELECTION;
00267 fd |= mcDRW_ALLOW_TOTAL_SELECTION;
00268 }
00269
00270
00271 ptn = ptd = pt;
00272 if (flags & mcDRW_USEPOINT) {
00273
00274
00275
00276 if (num.Inside(pt)) {
00277
00278
00279 fd |= mcDRW_NONACTIVE;
00280 ptd = wxDefaultPosition;
00281 f = 1;
00282
00283 } else if (den.Inside(pt)) {
00284
00285
00286 fn |= mcDRW_NONACTIVE;
00287 ptn = wxDefaultPosition;
00288 f = -1;
00289
00290 } else {
00291
00292
00293
00294 f = 1000;
00295 ptn = ptd = wxDefaultPosition;
00296 fn |= mcDRW_NONACTIVE;
00297 fd |= mcDRW_NONACTIVE;
00298 }
00299 }
00300
00301
00302 numid = data_GetNum().gui_Draw(hDC, num.x, num.y, fn, ptn);
00303 denid = data_GetDen().gui_Draw(hDC, den.x, den.y, fd, ptd);
00304
00305
00306 y += sgui_nSpaceAboveBelow+data_GetNum().gui_GetHeight()+sgui_nSpaceBetween;
00307
00308
00309 hDC.SetPen(*wxBLACK_PEN);
00310 int thickness = mcElementHelpers::gui_GetThickness(&hDC);
00311 for (int i=0; i < thickness; i++, y++)
00312 hDC.DrawLine(x+sgui_nAdditionalSpace/2, y,
00313 x+gui_GetWidth()-sgui_nAdditionalSpace/2, y);
00314
00315
00316 switch (f) {
00317 case 0:
00318 return data_GetID();
00319 case 1:
00320 return numid;
00321 case -1:
00322 return denid;
00323 }
00324
00325
00326 return mcDRW_NOACTIVEELEM;
00327 }
00328
00329 mcInputRes mcFractionHelpers::gui_Input(const mcKey &key, mcElement *pnew)
00330 {
00331 int res;
00332
00333
00334 if (key.MatchKey(*sgui_pNewFraction) &&
00335 !data_hasProperty(mcEP_INITIALIZED)) {
00336
00337
00338 data_GetNum().gui_AddNewEmptyMonomial();
00339 data_GetDen().gui_AddNewEmptyMonomial();
00340
00341 data_AddProperty(mcEP_INITIALIZED);
00342 gui_RecalcSize();
00343
00344 return mcIR_OKAY;
00345 }
00346
00347 switch (mgui_nCursorPos) {
00348 case mcFRACTION_LEFTMOST:
00349
00350
00351 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key))
00352 return mcIR_DELETE_PREVIOUS;
00353 if (mcMathCore::Get()->m_pCancelKey->MatchKey(key))
00354 return mcIR_DELETE_THIS;
00355 mcASSERT(0, wxT("Code should never get here; check isEndChar() function"));
00356
00357 case mcFRACTION_RIGHTMOST:
00358 if (mcMathCore::Get()->m_pDeleteKey->MatchKey(key))
00359 return mcIR_DELETE_THIS;
00360 if (mcMathCore::Get()->m_pCancelKey->MatchKey(key))
00361 return mcIR_DELETE_NEXT;
00362 mcASSERT(0, wxT("Code should never get here; check isEndChar() function"));
00363
00364 case mcFRACTION_INSIDENUM:
00365 res = data_GetNum().gui_Input(key, pnew);
00366
00367 if (res == mcIR_DELETE_PREVIOUS || res == mcIR_DELETE_THIS)
00368 return mcIR_DELETE_THIS;
00369
00370 gui_RecalcSize();
00371 break;
00372
00373 case mcFRACTION_INSIDEDEN:
00374 res = data_GetDen().gui_Input(key, pnew);
00375
00376 if (res == mcIR_DELETE_PREVIOUS || res == mcIR_DELETE_THIS)
00377 return mcIR_DELETE_THIS;
00378
00379 gui_RecalcSize();
00380 break;
00381 }
00382
00383 return mcIR_OKAY;
00384 }
00385
00386 mcInsertRes mcFractionHelpers::gui_Insert(const mcElement &toinsert, mcElement *newelem)
00387 {
00388 switch (mgui_nCursorPos) {
00389 case mcFRACTION_INSIDENUM:
00390 data_GetNum().gui_Insert(toinsert, NULL);
00391 break;
00392
00393 case mcFRACTION_INSIDEDEN:
00394 data_GetDen().gui_Insert(toinsert, NULL);
00395 break;
00396
00397 default:
00398 mcASSERT(0, wxT("Invalid cursor position"));
00399 }
00400
00401 return mcINSR_OKAY;
00402 }
00403
00404 mcMoveCursorRes mcFractionHelpers::gui_MoveCursor(mcMoveCursorFlag flags, long modifiers)
00405 {
00406 int result;
00407
00408 switch (mgui_nCursorPos) {
00409 case mcFRACTION_LEFTMOST:
00410 if (flags == mcMCF_LEFT) {
00411 return mcMCR_SETFOCUS_PREVIOUS;
00412 }
00413 if (flags == mcMCF_RIGHT) {
00414 mgui_nCursorPos = mcFRACTION_INSIDENUM;
00415 data_GetNum().gui_SetCursorPos(mcCP_BEGIN);
00416 }
00417 if (flags == mcMCF_UP)
00418 return mcMCR_SETFOCUS_ABOVE;
00419 if (flags == mcMCF_DOWN)
00420 return mcMCR_SETFOCUS_BELOW;
00421 break;
00422
00423 case mcFRACTION_RIGHTMOST:
00424 if (flags == mcMCF_LEFT) {
00425 mgui_nCursorPos = mcFRACTION_INSIDENUM;
00426 }
00427 if (flags == mcMCF_RIGHT) {
00428 return mcMCR_SETFOCUS_NEXT;
00429 }
00430 if (flags == mcMCF_UP)
00431 return mcMCR_SETFOCUS_ABOVE;
00432 if (flags == mcMCF_DOWN)
00433 return mcMCR_SETFOCUS_BELOW;
00434 break;
00435
00436 case mcFRACTION_INSIDENUM:
00437
00438
00439 result = data_GetNum().gui_MoveCursor(flags, modifiers);
00440
00441
00442 if (result == mcMCR_SETFOCUS_PREVIOUS) {
00443 mgui_nCursorPos = mcFRACTION_LEFTMOST;
00444 }
00445 if (result == mcMCR_SETFOCUS_NEXT) {
00446 mgui_nCursorPos = mcFRACTION_RIGHTMOST;
00447 }
00448 if (result == mcMCR_SETFOCUS_ABOVE) {
00449 return mcMCR_SETFOCUS_ABOVE;
00450 }
00451 if (result == mcMCR_SETFOCUS_BELOW) {
00452 mgui_nCursorPos = mcFRACTION_INSIDEDEN;
00453 data_GetDen().gui_SetCursorPos(mcCP_BEGIN);
00454 }
00455
00456 break;
00457
00458 case mcFRACTION_INSIDEDEN:
00459
00460 result = data_GetDen().gui_MoveCursor(flags, modifiers);
00461
00462
00463 if (result == mcMCR_SETFOCUS_PREVIOUS) {
00464 mgui_nCursorPos = mcFRACTION_LEFTMOST;
00465 }
00466 if (result == mcMCR_SETFOCUS_NEXT) {
00467 mgui_nCursorPos = mcFRACTION_RIGHTMOST;
00468 }
00469 if (result == mcMCR_SETFOCUS_ABOVE) {
00470 mgui_nCursorPos = mcFRACTION_INSIDENUM;
00471 data_GetNum().gui_SetCursorPos(mcCP_BEGIN);
00472 }
00473 if (result == mcMCR_SETFOCUS_BELOW) {
00474 return mcMCR_SETFOCUS_BELOW;
00475 }
00476
00477 break;
00478 }
00479
00480 return mcMCR_OKAY;
00481 }
00482
00483 int mcFractionHelpers::gui_MoveCursorUsingPoint(wxDC &dc, const wxPoint &pt)
00484 {
00485
00486 wxRect num(gui_GetNumPos(), data_GetNum().gui_GetSize());
00487 wxRect den(gui_GetDenPos(), data_GetDen().gui_GetSize());
00488
00489 if (num.Inside(pt)) {
00490 mgui_nCursorPos = mcFRACTION_INSIDENUM;
00491 return data_GetNum().gui_MoveCursorUsingPoint(dc, pt);
00492 }
00493 if (den.Inside(pt)) {
00494 mgui_nCursorPos = mcFRACTION_INSIDEDEN;
00495 return data_GetDen().gui_MoveCursorUsingPoint(dc, pt);
00496 }
00497
00498 return mcMCR_OKAY;
00499 }
00500
00501 int mcFractionHelpers::gui_GetRelCursorPos(wxDC &hDC, wxPoint *pt) const
00502 {
00503 int n;
00504
00505 switch (mgui_nCursorPos) {
00506 case mcFRACTION_LEFTMOST:
00507 pt->x = 0;
00508 pt->y = 0;
00509 return gui_GetSize().GetHeight();
00510
00511 case mcFRACTION_RIGHTMOST:
00512 pt->x = gui_GetSize().GetWidth();
00513 pt->y = 0;
00514 return gui_GetSize().GetHeight();
00515
00516 case mcFRACTION_INSIDENUM:
00517 n = data_GetNum().gui_GetRelCursorPos(hDC, pt);
00518 pt->x += gui_GetNumPos().x;
00519 pt->y += gui_GetNumPos().y;
00520 return n;
00521
00522 case mcFRACTION_INSIDEDEN:
00523 n = data_GetDen().gui_GetRelCursorPos(hDC, pt);
00524 pt->x += gui_GetDenPos().x;
00525 pt->y += gui_GetDenPos().y;
00526 return n;
00527 }
00528
00529 return 0;
00530 }
00531
00532 void mcFractionHelpers::gui_SetCursorPos(const mcCursorPos &cp)
00533 {
00534 if (cp.isBegin())
00535 mgui_nCursorPos = mcFRACTION_LEFTMOST;
00536 else if (cp.isEnd())
00537 mgui_nCursorPos = mcFRACTION_RIGHTMOST;
00538 else
00539 mcASSERT(0, wxT("Cannot accept these flags"));
00540 }
00541
00542 void mcFractionHelpers::gui_GetCursorPos(mcCursorPos &cp) const
00543 {
00544 if (mgui_nCursorPos == mcFRACTION_LEFTMOST)
00545 cp.gui_Push(mcCP_BEGIN);
00546 else if (mgui_nCursorPos == mcFRACTION_RIGHTMOST)
00547 cp.gui_Push(mcCP_END);
00548 else
00549 cp.gui_Push(mgui_nCursorPos);
00550 }
00551
00552 mcElement mcFractionHelpers::gui_GetSelection() const
00553 {
00554 bool n = data_GetNum().gui_isSelected(),
00555 d = data_GetDen().gui_isSelected();
00556
00557 if (n && d) {
00558
00559
00560 mcASSERT(gui_isAllSelected(), wxT("If both num & den are selected, the element ")
00561 wxT("should be marked as completely selected"));
00562
00563
00564 mcElement *toreturn = new mcFraction(this);
00565 return *toreturn;
00566
00567 } else if (n) {
00568
00569
00570 return data_GetNum().gui_GetSelection();
00571
00572 }
00573
00574 return data_GetDen().gui_GetSelection();
00575 }
00576
00577 void mcFractionHelpers::gui_DeleteSelection()
00578 {
00579 mcElementHelpers::gui_DeleteSelection();
00580
00581
00582 if (data_GetNum().data_GetCount() == 0)
00583 data_GetNum().gui_AddNewEmptyMonomial();
00584 if (data_GetDen().data_GetCount() == 0)
00585 data_GetDen().gui_AddNewEmptyMonomial();
00586
00587 gui_RecalcSize();
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 wxXml2Node mcFractionHelpers::io_GetMathML(bool bGetPresentation) const
00601 {
00602 wxXml2Node maintag;
00603
00604
00605 if (bGetPresentation) {
00606
00607 maintag.CreateTemp(wxXML_ELEMENT_NODE, wxXml2EmptyDoc, wxT("mfrac"));
00608
00609 } else {
00610
00611 maintag.CreateTemp(wxXML_ELEMENT_NODE, wxXml2EmptyDoc, wxT("apply"));
00612 wxXml2Node divide(wxXML_ELEMENT_NODE, maintag, wxT("divide"));
00613 }
00614
00615
00616 wxXml2Node num = data_GetNum().io_GetMathML(bGetPresentation),
00617 den = data_GetDen().io_GetMathML(bGetPresentation);
00618 maintag.AddChild(num);
00619 maintag.AddChild(den);
00620
00621 return maintag;
00622 }
00623
00624 bool mcFractionHelpers::io_CheckBracketNeed(const mcPolynomial &p, const wxString &exp) const
00625 {
00626 bool res = FALSE;
00627
00628
00629
00630
00631 res |= (p.data_GetCount() > 1);
00632
00633 mcMonomial m = mcMonomial(p.data_GetElemOfType(0, mcET_MONOMIAL));
00634 if (m != mcEmptyElement && m.data_GetCount() > 0) {
00635
00636
00637
00638 res |= (m.data_Get(0).data_GetType() != mcET_BRACKET && exp.Len() > 3);
00639 }
00640
00641 return res;
00642 }
00643
00644 wxString mcFractionHelpers::io_GetInlinedExpr() const
00645 {
00646 wxString strNum = data_GetNum().io_GetInlinedExpr();
00647 wxString strDen = data_GetDen().io_GetInlinedExpr();
00648
00649
00650 bool bracketizeNum = io_CheckBracketNeed(data_GetNum(), strNum);
00651 bool bracketizeDen = io_CheckBracketNeed(data_GetDen(), strDen);
00652
00653 if (bracketizeNum) strNum = wxT("(") + strNum + wxT(")");
00654 if (bracketizeDen) strDen = wxT("(") + strDen + wxT(")");
00655
00656
00657 return strNum + wxT("/") + strDen;
00658 }
00659
00660 bool mcFractionHelpers::io_ImportPresentationMathML(wxXml2Node tag, wxString &pErr)
00661 {
00662 mcASSERT(tag.GetName() == wxT("mfrac"), wxT("Error in mcFractionHelpers::io_isBeginTag()"));
00663
00664
00665 wxXml2Node num = tag.GetChildren();
00666 wxXml2Node den = num.GetNext();
00667
00668 if (den.GetNext() != wxXml2EmptyNode) {
00669 pErr = wxT("Found an <MFRAC> tag with more than two nested tags.");
00670 return FALSE;
00671 }
00672
00673 if (den == wxXml2EmptyNode || num == wxXml2EmptyNode) {
00674 pErr = wxT("Found an <MFRAC> tag with less than two nested tags.");
00675 return FALSE;
00676 }
00677
00678 if (num.GetName() != wxT("mrow"))
00679 num.Encapsulate(wxT("mrow"));
00680 if (den.GetName() != wxT("mrow"))
00681 den.Encapsulate(wxT("mrow"));
00682 num.SetNext(den);
00683 tag.SetChildren(num);
00684
00685 if (!data_GetNum().io_ImportPresentationMathML(num, pErr))
00686 return FALSE;
00687 if (!data_GetDen().io_ImportPresentationMathML(den, pErr))
00688 return FALSE;
00689
00690 return TRUE;
00691 }
00692
00693 bool mcFractionHelpers::io_ImportInlinedExpr(const wxString &str, int *count, wxString &pErr)
00694 {
00695 mcUNUSED(str);
00696 mcUNUSED(count);
00697 mcUNUSED(pErr);
00698
00699
00700 mcASSERT(0, wxT("mcFractionIO MathML import functions should never be called ")
00701 wxT("because mcDivOp will import all the data for the '/' symbols ")
00702 wxT("which will be then converted to mcFraction later..."));
00703 return FALSE;
00704 }
00705
00706 void mcFractionHelpers::io_SetNum(const wxString &num)
00707 {
00708 wxString str;
00709
00710
00711
00712 data_GetNum().io_ImportInlinedExpr(num, NULL, str);
00713 }
00714
00715 void mcFractionHelpers::io_SetDen(const wxString &den)
00716 {
00717 wxString str;
00718
00719
00720
00721 data_GetDen().io_ImportInlinedExpr(den, NULL, str);
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731 void mcFractionHelpers::math_SetExp(const mcPolynomial &p)
00732 {
00733
00734
00735
00736
00737
00738
00739
00740
00741 mcASSERT(0, wxT(""));
00742 }
00743
00744 bool mcFractionHelpers::math_Compare(const mcElement &p, long flags) const
00745 {
00746 if (p.data_GetType() != mcET_FRACTION)
00747 return FALSE;
00748
00749
00750 mcFraction f(p);
00751 return data_GetNum().math_Compare(f.data_GetNum(), flags) &&
00752 data_GetDen().math_Compare(f.data_GetDen(), flags);
00753 }
00754
00755 mcMathType mcFractionHelpers::math_GetMathType() const
00756 {
00757 mcMathType num = data_GetNum().math_GetMathType();
00758 mcMathType den = data_GetDen().math_GetMathType();
00759
00760
00761 num.math_MultiplyBy(den);
00762
00763
00764
00765 if (data_GetDen().math_ContainsUnknowns())
00766 num.m_tMath1 = mcMTL1_RATIONAL;
00767
00768 return num;
00769 }
00770
00771 mcRealValue mcFractionHelpers::math_Evaluate() const
00772 {
00773 mcRealValue num = data_GetNum().math_Evaluate();
00774 mcRealValue den = data_GetDen().math_Evaluate();
00775
00776
00777 if (!num.isValid() ||
00778 !den.isValid())
00779 return *mcRealValue::pNAN;
00780
00781
00782 return num/den;
00783 }
00784
00785 void mcFractionHelpers::math_Flip()
00786 {
00787
00788 mcPolynomial tmp = data_GetNum();
00789 data_GetNum() = data_GetDen();
00790 data_GetDen() = tmp;
00791 }
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 bool mcFractionHelpers::math_CanBeMultWith(const mcElement &p) const
00802 { return TRUE; }
00803
00804 bool mcFractionHelpers::math_CanBeAddedWith(const mcElement &p) const
00805 { return TRUE; }
00806
00807 bool mcFractionHelpers::math_CanBeDivBy(const mcElement &p) const
00808 { return TRUE; }
00809
00810
00811
00812 mcBasicOpRes mcFractionHelpers::math_Add(const mcElement &p, mcElement *pp, bool add)
00813 {
00814 switch (p.data_GetType()) {
00815 case mcET_FRACTION:
00816 {
00817 mcFraction f(p);
00818
00819
00820 mcMonomial lcm(data_GetDen().math_GetLCM(f.data_GetDen()));
00821 mcPolynomial common;
00822 common.data_AddNewMonomial(lcm);
00823
00824
00825
00826 mcPolynomial mult(common);
00827 mult.math_SimpleDivideBy(data_GetDen());
00828 data_GetNum().math_SimpleMultiplyBy(mult);
00829
00830 mult.data_DeleteAll();
00831
00832
00833
00834 mult = common;
00835 mult.math_SimpleDivideBy(f.data_GetDen());
00836 mcPolynomial tmp(f.data_GetNum());
00837 tmp.math_SimpleMultiplyBy(mult);
00838
00839
00840 if (add)
00841 data_GetNum().math_SimpleAdd(tmp);
00842 else
00843 data_GetNum().math_SimpleSubtract(tmp);
00844
00845
00846 data_SetDen(common);
00847 }
00848 break;
00849
00850 case mcET_NUMBER:
00851 case mcET_SYMBOL:
00852 case mcET_MONOMIAL:
00853 case mcET_POLYNOMIAL:
00854 case mcET_RADICAL:
00855 case mcET_BRACKET:
00856 case mcET_FUNCTION:
00857 {
00858
00859
00860 mcPolynomial tmp = data_GetDen();
00861 tmp.math_SimpleMultiplyBy(p);
00862
00863
00864 data_GetNum().math_SimpleAdd(tmp, add);
00865 }
00866 break;
00867
00868 default:
00869 mcASSERT(0, wxT("Something is really wrong..."));
00870 break;
00871 }
00872
00873 return mcBOR_REMOVE_OPERAND;
00874 }
00875
00876 mcBasicOpRes mcFractionHelpers::math_MultiplyBy(const mcElement &p, mcElement *pp)
00877 {
00878 mcASSERT(p.math_isValidMath(), wxT("Invalid operand"));
00879
00880 if (p.data_GetType() == mcET_FRACTION) {
00881
00882 mcFraction f(p);
00883
00884
00885
00886
00887
00888
00889
00890 data_GetNum().math_SimpleMultiplyBy(f.data_GetNum());
00891 data_GetDen().math_SimpleMultiplyBy(f.data_GetDen());
00892
00893 } else {
00894
00895
00896
00897
00898
00899
00900
00901 data_GetNum().math_SimpleMultiplyBy(p);
00902 }
00903
00904 return mcBOR_REMOVE_OPERAND;
00905 }
00906
00907 mcBasicOpRes mcFractionHelpers::math_DivideBy(const mcElement &p, mcElement *pp)
00908 {
00909 mcASSERT(p.math_isValidMath(), wxT("Invalid operand"));
00910
00911 if (p.data_GetType() == mcET_FRACTION) {
00912
00913 mcFraction f(p);
00914
00915
00916
00917
00918
00919
00920
00921 f.math_Flip();
00922 f.data_Check();
00923 *pp = f;
00924
00925 return mcBOR_REPLACE_OPERAND_AND_SET_MULTOP;
00926
00927 } else {
00928
00929
00930
00931
00932
00933
00934
00935 data_GetDen().math_SimpleMultiplyBy(p);
00936 }
00937
00938 return mcBOR_REMOVE_OPERAND;
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948 mcExpSimRes mcFractionHelpers::math_Simplify(long flags, mcElement *newelem)
00949 {
00950 mcPolynomial &n = data_GetNum(), &d = data_GetDen();
00951
00952
00953 mcExpSimRes n1 = n.math_Simplify(flags);
00954 mcExpSimRes n2 = d.math_Simplify(flags);
00955
00956
00957 if (n1 != mcESR_DONE || n2 != mcESR_DONE)
00958 return mcESR_NOTFINISHED;
00959
00960
00961 if (n.math_isFirstMonomialNegative() && d.math_isFirstMonomialNegative()) {
00962
00963
00964 n.math_ChangeAllSigns();
00965 d.math_ChangeAllSigns();
00966 return mcESR_NOTFINISHED;
00967 }
00968
00969 if (n.math_isFirstMonomialNegative()) {
00970
00971
00972
00973
00974 n.math_ChangeAllSigns();
00975 return mcESR_CHANGE_SIGN;
00976 }
00977
00978
00979
00980
00981
00982 if (d.math_GetCount() == 1) {
00983
00984 mcRealValue value = d.math_Evaluate();
00985
00986
00987 if (value == -1.0) {
00988 n.math_ChangeAllSigns();
00989 value = 1.0;
00990 }
00991
00992 if (value == 1.0) {
00993
00994
00995 mcBracket br;
00996 br.data_SetContent(n);
00997
00998
00999
01000 (*newelem) = br;
01001
01002 return mcESR_REPLACE_THIS;
01003 }
01004 }
01005
01006
01007 if (n.math_isFactorized() && d.math_isFactorized())
01008 return math_SimplifyFactors(flags, newelem);
01009
01010
01011
01012 return mcESR_DONE;
01013 }
01014
01015 mcExpSimRes mcFractionHelpers::math_SimplifyFactors(long flags, mcElement *newelem)
01016 {
01017 mcPolynomial &n = data_GetNum(), &d = data_GetDen();
01018
01019 mcUNUSED(newelem);
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 mcMonomial &m1 = n.math_Get(0);
01031 mcMonomial &m2 = d.math_Get(0);
01032
01033 for (int i=0; i < m1.math_GetCount(); i++) {
01034
01035 mcElement &first = (mcElement &)m1.math_Get(i);
01036 for (int j=0; j < m2.math_GetCount(); j++) {
01037
01038 mcElement &second = (mcElement &)m2.math_Get(j);
01039 if (first.math_CanBeDivBy(second)) {
01040
01041 mcMATHLOG(wxT("mcFractionHelpers::math_SimplifyFactors - dividing ")
01042 wxT("[%s] by [%s]"), mcTXT(first), mcTXT(second));
01043
01044
01045
01046 mcElement replacement;
01047 mcBasicOpRes r = first.math_DivideBy(second, &replacement);
01048
01049
01050 switch(r) {
01051 case mcBOR_INVALID:
01052 mcASSERT(0, wxT("Something was wrong"));
01053 break;
01054
01055 case mcBOR_REPLACE_OPERAND:
01056 m2.data_AddElements(&replacement, 1,
01057 m2.math_MathToDataIdx(j), TRUE);
01058 m2.data_Check();
01059 break;
01060
01061 case mcBOR_REMOVE_OPERAND:
01062 m2.math_Remove(j, FALSE);
01063 break;
01064
01065 default:
01066 mcASSERT(0, wxT("TODO"));
01067 }
01068
01069 return mcESR_NOTFINISHED;
01070 }
01071 }
01072 }
01073
01074
01075
01076
01077 return mcESR_DONE;
01078 }
01079
01080 mcExpSimRes mcFractionHelpers::math_Expand(long flags, mcElement *newelem)
01081 {
01082 mcPolynomial &n = data_GetNum(), &d = data_GetDen();
01083 mcExpSimRes n1 = n.math_Expand(flags);
01084 mcExpSimRes n2 = d.math_Expand(flags);
01085
01086
01087 if (n1 != mcESR_DONE || n2 != mcESR_DONE)
01088 return mcESR_NOTFINISHED;
01089
01090 return mcESR_DONE;
01091 }
01092
01093
01094
01095
01096
01097
01098
01099 mcMonomial mcFractionHelpers::math_GetLCM(const mcElement &p) const
01100 {
01101 mcFraction f(p);
01102 mcFraction res;
01103
01104 mcPolynomial num = data_GetNum().math_GetLCM(f.data_GetNum());
01105 mcPolynomial den = data_GetDen().math_GetLCM(f.data_GetDen());
01106 res.data_SetNum(num);
01107 res.data_SetDen(den);
01108
01109 return res;
01110 }
01111
01112 mcMonomial mcFractionHelpers::math_GetGCD(const mcElement &p) const
01113 {
01114 mcFraction f(p);
01115 mcFraction res;
01116
01117 mcPolynomial num = data_GetNum().math_GetGCD(f.data_GetNum());
01118 mcPolynomial den = data_GetDen().math_GetGCD(f.data_GetDen());
01119 res.data_SetNum(num);
01120 res.data_SetDen(den);
01121
01122 return res;
01123 }
01124
01125 mcBasicOpRes mcFractionHelpers::math_RaiseTo(const mcPolynomial &p)
01126 {
01127 data_GetNum().math_SimpleRaiseTo(p);
01128 data_GetDen().math_SimpleRaiseTo(p);
01129
01130 return mcBOR_REMOVE_OPERAND;
01131 }
01132
01133