00001 00002 // MathCore = a WYSIWYG equation editor + a powerful math engine // 00003 // Copyright (C) 2003 by Francesco Montorsi // 00004 // // 00005 // This library is free software; you can redistribute it and/or // 00006 // modify it under the terms of the GNU Lesser General Public // 00007 // License as published by the Free Software Foundation; either // 00008 // version 2.1 of the License, or (at your option) any later // 00009 // version. // 00010 // // 00011 // This library is distributed in the hope that it will be useful, // 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00014 // GNU Lesser General Public License for more details. // 00015 // // 00016 // You should have received a copy of the GNU Lesser General Public // 00017 // License along with this program; if not, write to the Free // 00018 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, // 00019 // MA 02111-1307, USA. // 00020 // // 00021 // For any comment, suggestion or feature request, please contact // 00022 // the administrator of the project at frm@users.sourceforge.net // 00023 // // 00030 00031 00032 // optimization for GCC compiler 00033 #ifdef __GNUG__ 00034 #pragma implementation "MathCore.h" 00035 #endif 00036 00037 // includes 00038 #include "mc/mcprec.h" 00039 #ifdef __BORLANDC__ 00040 #pragma hdrstop 00041 #endif 00042 00043 #ifndef mcPRECOMP 00044 #include "mc/MathCore.h" 00045 #include "mc/EmptyBox.h" 00046 #include "mc/Number.h" 00047 #include "mc/Bracket.h" 00048 #include "mc/Fraction.h" 00049 #include "mc/Function.h" 00050 #include "mc/Radical.h" 00051 #include "mc/Text.h" 00052 #include "mc/Symbol.h" 00053 #include "mc/Operator.h" 00054 #include "mc/AddSubOp.h" 00055 #include "mc/MultDivOp.h" 00056 #include "mc/Monomial.h" 00057 #include "mc/MathMng.h" 00058 #include "mc/Parenthesis.h" 00059 00060 #include "mc/PolySolver.h" // solvers 00061 #include "mc/BisectSolver.h" 00062 #include "mc/GenericSolver.h" 00063 #endif 00064 00065 00066 // Definition of the STATIC variables of mcMathCore 00067 mcMathCore *mcMathCore::g_pTheInstance = NULL; 00068 void (*mcMathCore::OnError)(const wxString &) = NULL; 00069 mcSolverArray mcMathCore::arrSolvers; 00070 00071 #ifdef mcDETECT_MEMORY_LEAKS 00072 HFILE mcMathCore::m_hLogFile = NULL; 00073 FILE *mcMathCore::m_fLogAllocFile = NULL; 00074 char mcMathCore::m_szMsg[]; 00075 #endif 00076 00077 00078 00079 00080 // --------------------- 00081 // mcMATHCORE 00082 // --------------------- 00083 00084 mcMathCore::mcMathCore() 00085 { 00086 m_bIOEnabled = m_bGUIEnabled = m_bMathEnabled = FALSE; 00087 00088 // the number of spaces used to indent debug output 00089 m_nIndentationStep = 4; 00090 m_nMaxSharing = -1; 00091 } 00092 00093 mcMathCore::~mcMathCore() 00094 { 00095 // shutdown subsystems: order is important !!! 00096 if (isGUIEnabled()) CleanupGUI(); 00097 if (isIOEnabled()) CleanupIO(); 00098 if (isMathEnabled()) CleanupMath(); 00099 00100 wxLog *logtarget = wxLog::SetActiveTarget(NULL); 00101 mcSAFE_DELETE(logtarget); 00102 } 00103 00104 // this one is static 00105 mcMathCore *mcMathCore::Get() 00106 { 00107 mcASSERT(g_pTheInstance != NULL, 00108 wxT("Before using mcMathCore::Get() you must call mcMathCore::Setup()")); 00109 return g_pTheInstance; 00110 } 00111 00112 // this one is static 00113 void mcMathCore::Set(mcMathCore *p) 00114 { 00115 if (g_pTheInstance != NULL) 00116 delete g_pTheInstance; 00117 g_pTheInstance = p; 00118 } 00119 00120 void mcMathCore::Setup(bool bIO, bool bMath, bool bGUI) 00121 { 00122 // create the global instance of the class 00123 mcMathCore::g_pTheInstance = new mcMathCore(); 00124 00125 // and then, init it 00126 // (this step cannot be done in the constructor of mcMathCore 00127 // because it generates calls to mcMathCore::Get() which needs 00128 // a working mcMathCore::g_pTheInstance pointer...) 00129 mcMathCore::g_pTheInstance->Init(bIO, bMath, bGUI); 00130 } 00131 00132 void mcMathCore::Init(bool bIO, bool bMath, bool bGUI) 00133 { 00134 #ifdef mcENABLE_LOG 00135 wxLog::SetActiveTarget(new mcLog()); 00136 #endif 00137 00138 // the order is important !!! 00139 if (bMath) SetupMath(); 00140 if (bIO) SetupIO(); 00141 if (bGUI) SetupGUI(NULL); 00142 00143 mcElementHelpers::Init(); 00144 } 00145 00146 void mcMathCore::Cleanup() 00147 { 00148 // delete the global istance of this class 00149 mcSAFE_DELETE(mcMathCore::g_pTheInstance); 00150 00151 #if 0 //def mcENABLE_LOG 00152 wxLog *p = wxLog::GetActiveTarget(); 00153 wxLog::SetActiveTarget(NULL); 00154 mcSAFE_DELETE(p); 00155 #endif 00156 } 00157 00158 void mcMathCore::SetupIO() 00159 { 00160 m_bIOEnabled = TRUE; 00161 00162 wxXml2::Init(); 00163 //data_UpdateElemArray(); 00164 } 00165 00166 void mcMathCore::CleanupIO() 00167 { 00168 wxXml2::Cleanup(); 00169 00170 m_bIOEnabled = FALSE; 00171 //data_UpdateElemArray(); 00172 } 00173 00174 void mcMathCore::SetupMath() 00175 { 00176 m_bMathEnabled = TRUE; 00177 00178 // first of all init mcRealValue class 00179 mcRealValue::Init(); 00180 00181 // init mcSymbol arrays 00182 mcSymbol::InitSymbols(); 00183 00184 // set the default step threshold 00185 mcMathCore::m_fStepThreshold = mcDEFAULT_STEP_THRESHOLD; 00186 00187 // load parameters, constants, unknowns and functions 00188 // 00189 // FIXME: do we have to load any standard function/symbol, or 00190 // we leave this task to the user ? 00191 //mcSymbol::LoadSymbols(); 00192 //mcFunction::LoadFunctions(); 00193 //mcSymbol::CheckSymbols(); 00194 00195 // init the interpreter 00196 #ifdef mcUSE_WXSCRIPT 00197 wxScriptInterpreter::Init(); 00198 #endif 00199 00200 // create some useful objects 00201 mcNumberHelpers::smath_pFour = new mcNumber(4.0); 00202 mcNumberHelpers::smath_pTwo = new mcNumber(2.0); 00203 mcNumberHelpers::smath_pOne = new mcNumber(1.0); 00204 mcNumberHelpers::smath_pMinusOne = new mcNumber(-1.0); 00205 mcNumberHelpers::smath_pZero = new mcNumber(0.0); 00206 00207 mcMonomialHelpers::smath_pZero = new mcMonomial; 00208 mcMonomialHelpers::smath_pZero->math_WrapNumber(0.0); 00209 mcMonomialHelpers::smath_pOne = new mcMonomial; 00210 mcMonomialHelpers::smath_pOne->math_WrapSimple(*mcNumberHelpers::smath_pOne); 00211 00212 mcPolynomialHelpers::smath_pEmpty = new mcPolynomial; 00213 mcPolynomialHelpers::smath_pOne = new mcPolynomial; 00214 mcPolynomialHelpers::smath_pOne->math_WrapSimple(*mcNumberHelpers::smath_pOne); 00215 00216 00217 // check them 00218 mcMonomialHelpers::smath_pZero->data_Check(); 00219 mcMonomialHelpers::smath_pOne->data_Check(); 00220 mcPolynomialHelpers::smath_pEmpty->data_Check(); 00221 mcPolynomialHelpers::smath_pOne->data_Check(); 00222 /* mcRange::pR = new mcRange(*mcRealValue::pNegInf, *mcRealValue::pPosInf, mcSET_N); 00223 mcExtRange::pR = new mcExtRange(*mcRange::pR); 00224 */ 00225 mcTextHelpers::smath_pEmpty = new mcText(); 00226 00227 // init random generator with the number of 00228 // of seconds since GMT 00:00:00 Jan 1st 1970 00229 srand(wxGetUTCTime()); 00230 00231 // no functions using the mcMathCore::pElem array should be 00232 // called in the SetupXXX() functions 00233 } 00234 00235 void mcMathCore::CleanupMath() 00236 { 00237 m_bMathEnabled = FALSE; 00238 00239 // close the interpreter 00240 #ifdef mcUSE_WXSCRIPT 00241 wxScriptInterpreter::Cleanup(); 00242 #endif 00243 00244 // delete the STATIC objects 00245 mcSAFE_DELETE(mcNumberHelpers::smath_pOne); 00246 mcSAFE_DELETE(mcNumberHelpers::smath_pTwo); 00247 mcSAFE_DELETE(mcNumberHelpers::smath_pFour); 00248 mcSAFE_DELETE(mcNumberHelpers::smath_pMinusOne); 00249 mcSAFE_DELETE(mcNumberHelpers::smath_pZero); 00250 mcSAFE_DELETE(mcPolynomialHelpers::smath_pOne); 00251 mcSAFE_DELETE(mcPolynomialHelpers::smath_pEmpty); 00252 mcSAFE_DELETE(mcMonomialHelpers::smath_pOne); 00253 mcSAFE_DELETE(mcMonomialHelpers::smath_pZero); 00254 00255 mcSAFE_DELETE(mcRange::pR); 00256 mcSAFE_DELETE(mcExtRange::pR); 00257 mcSAFE_DELETE(mcTextHelpers::smath_pEmpty); 00258 00259 // clear math arrays 00260 arrSolvers.data_Clear(); 00261 mcSymbol::CleanupSymbols(); 00262 00263 // de-init mcRealValue classes 00264 mcRealValue::Cleanup(); 00265 mcElementHelpers::Cleanup(); 00266 00267 // delete pElem array 00268 //data_UpdateElemArray(); 00269 } 00270 00271 void mcMathCore::SetupGUI(void (*OnErrorFnc)(const wxString &)) 00272 { 00273 m_bGUIEnabled = TRUE; 00274 00275 // be sure that also wxWidgets' GUI is correctly init... 00276 // if the wxXXXXX colors are okay, then the GUI should have been set up 00277 mcASSERT(wxWHITE != NULL, wxT("wxWidgets' GUI seems to be offline...")); 00278 00279 //strMathMLOp[0] = { wxT("plus"), wxT("minus"), wxT("times"), "divide" }; 00280 00281 // setup STATIC variables 00282 mcElementHelpers::sgui_pSelectionBrush = new wxBrush(wxColour(0x40ffff), wxSOLID); 00283 mcElementHelpers::sgui_pActivationBrush = new wxBrush(wxColour(0xfadcb4), wxSOLID); 00284 mcElementArrayHelpers::sgui_pSelectionPen = new wxPen(wxColour(0, 0, 0), 1, wxDOT); 00285 mcEmptyBoxHelpers::sgui_pEmptyBoxBrush = new wxBrush(wxColour(0xfad2be), wxSOLID); 00286 mcEmptyBoxHelpers::sgui_pNewEmptyBox = new mcKey(wxT("x+127")); 00287 mcFractionHelpers::sgui_pNewFraction = new mcKey(wxString::Format(wxT("cx+%d"), wxT('f'))); 00288 mcFunctionHelpers::sgui_pNewFunction = new mcKey(wxString::Format(wxT("csx+%d"), wxT('f'))); 00289 mcRadicalHelpers::sgui_pNewRadical = new mcKey(wxString::Format(wxT("cx+%d"), wxT('r'))); 00290 00291 // create some standard keys required by mcElementHelpers::sgui_Input() 00292 // functions; 00293 m_pDeleteKey = new mcKey(wxString::Format(wxT("+%d"), WXK_BACK)); 00294 m_pCancelKey = new mcKey(wxString::Format(wxT("+%d"), WXK_DELETE)); 00295 m_pNewLineKey = new mcKey(wxString::Format(wxT("+%d"), WXK_RETURN)); 00296 00297 // those are special keys... 00298 m_pEditExpKey = new mcKey(wxString::Format(wxT("x+%d"), WXK_RETURN)); 00299 m_pEditSubscriptKey = new mcKey(wxString::Format(wxT("cx+%d"), WXK_RETURN)); 00300 00301 // set the error handler function pointer 00302 OnError = OnErrorFnc; 00303 00304 // initialize the styles of mcElementGUI 00305 mcElementHelpers::gui_InitDefaultStyles(); 00306 mcMathMngHelpers::gui_InitStyles(); 00307 00308 //data_UpdateElemArray(); 00309 } 00310 00311 void mcMathCore::CleanupGUI() 00312 { 00313 m_bGUIEnabled = FALSE; 00314 00315 // delete mcMathCore variables 00316 mcSAFE_DELETE(m_pDeleteKey); 00317 mcSAFE_DELETE(m_pCancelKey); 00318 mcSAFE_DELETE(m_pNewLineKey); 00319 00320 mcSAFE_DELETE(m_pEditExpKey); 00321 mcSAFE_DELETE(m_pEditSubscriptKey); 00322 00323 00324 // delete the STATIC pointers allocated by the various classes 00325 // we must be sure all customizable pointers have been deleted: they can be deleted 00326 // only here because when a mcFraction, mcRadical, mcEmptyBox, ..., is deleted, 00327 // it cannot know if the customizable resource will be required by another 00328 // element.... 00329 mcSAFE_DELETE(mcElementHelpers::sgui_pSelectionBrush); 00330 mcSAFE_DELETE(mcElementHelpers::sgui_pActivationBrush); 00331 mcSAFE_DELETE(mcElementArrayHelpers::sgui_pSelectionPen); 00332 mcSAFE_DELETE(mcEmptyBoxHelpers::sgui_pEmptyBoxBrush); 00333 mcSAFE_DELETE(mcEmptyBoxHelpers::sgui_pNewEmptyBox); 00334 mcSAFE_DELETE(mcFractionHelpers::sgui_pNewFraction); 00335 mcSAFE_DELETE(mcFunctionHelpers::sgui_pNewFunction); 00336 mcSAFE_DELETE(mcRadicalHelpers::sgui_pNewRadical); 00337 00338 00339 // delete the style array and mark it as empty 00340 mcElementHelpers::gui_DeleteDefaultStyles(); 00341 mcMathMngHelpers::gui_DeleteStyles(); 00342 00343 //data_UpdateElemArray(); 00344 } 00345 00346 00347 00348 00349 00350 // -------------------------------- 00351 // mcMATHCORE - miscellaneous 00352 // -------------------------------- 00353 00354 bool mcMathCore::isGUIEnabled() const 00355 { return m_bGUIEnabled; } 00356 00357 bool mcMathCore::isMathEnabled() const 00358 { return m_bMathEnabled; } 00359 00360 bool mcMathCore::isIOEnabled() const 00361 { return m_bIOEnabled; } 00362 00363 bool mcMathCore::MatchEditKeys(const mcKey &key) 00364 { 00365 return m_pDeleteKey->MatchKey(key) || 00366 m_pCancelKey->MatchKey(key) || 00367 m_pEditSubscriptKey->MatchKey(key) || 00368 m_pEditExpKey->MatchKey(key); 00369 } 00370 00371 void mcMathCore::SyntaxError(wxString str) 00372 { 00373 // just send a message to the 'on error' registered function 00374 if (OnError != NULL) 00375 OnError(str); 00376 } 00377 00378 00379 00380 00381 00382 // -------------------------------- 00383 // mcMATHCORE - math functions 00384 // -------------------------------- 00385 00386 #define mcSAFE_ADD(x) \ 00387 { mcSolver *toadd = new x(); \ 00388 if (!arrSolvers.math_Add(toadd)) \ 00389 delete toadd; } 00390 00391 00392 void mcMathCore::LoadDefaultSolvers() 00393 { 00394 // generic solvers 00395 mcSAFE_ADD(mcSimplifySolver); 00396 mcSAFE_ADD(mcExpandSolver); 00397 00398 // the polynomial solver 00399 mcSAFE_ADD(mcPolySolver); 00400 00401 // the approximated bisection solver 00402 mcSAFE_ADD(mcBisectSolver); 00403 } 00404
[ Top ] |