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 // // 00031 00032 00033 00034 // optimization for GCC compiler 00035 #ifdef __GNUG__ 00036 #pragma implementation "Radical.h" 00037 #endif 00038 00039 00040 // includes 00041 #include "mc/mcprec.h" 00042 #ifdef __BORLANDC__ 00043 #pragma hdrstop 00044 #endif 00045 00046 #ifndef mcPRECOMP 00047 #include "mc/Radical.h" 00048 #include "mc/Monomial.h" 00049 #endif 00050 00051 00052 mcIMPLEMENT_MAIN_CLASS(mcRadical, mcExpContainer); 00053 00054 00055 // setup customizable variables 00056 int mcRadicalHelpers::sgui_nSpaceLeftRight = 4; 00057 int mcRadicalHelpers::sgui_nSpaceAboveBelow = 2; 00058 00059 wxString mcRadicalHelpers::sio_strGenericRoot = wxT("root"); 00060 wxString mcRadicalHelpers::sio_strSquareRoot = wxT("sqrt"); 00061 00062 // This is the special key which must be used to create a new fraction 00063 // through the mcElementGUI input system. 00064 // This is not a simple CTRL+R combination because gui_isBeginKey() will 00065 // return TRUE only if the given key is set as a special key. 00066 mcKey *mcRadicalHelpers::sgui_pNewRadical = NULL; 00067 00068 00069 00070 00071 00072 // ---------------------------------------- 00073 // mcRADICALGUI 00074 // ---------------------------------------- 00075 00076 bool mcRadicalHelpers::gui_isBeginKey(const mcKey &key) const 00077 { 00078 if (key.MatchKey(*sgui_pNewRadical)) 00079 return TRUE; 00080 return FALSE; 00081 } 00082 00083 bool mcRadicalHelpers::gui_isLeftPosEnabled() const 00084 { 00085 if (data_hasProperty(mcEP_HASEXPONENT)) 00086 return FALSE; 00087 return TRUE; 00088 } 00089 00090 int mcRadicalHelpers::gui_GetContentOffsetY() const 00091 { 00092 // take in count also the radical's sign thickness 00093 int h = mcElementHelpers::gui_GetThickness(NULL) + gui_GetSpaceAboveBelow(); 00094 00095 return h+(gui_GetHeight()-h-data_GetContent().gui_GetHeight())/2; 00096 } 00097 00098 int mcRadicalHelpers::gui_GetContentOffsetX() const 00099 { 00100 // take in count also exponent (or better, index) width 00101 return mcMAX(gui_GetExpSubSize(TRUE).GetWidth(), 5) + 00102 gui_GetVWidth() + gui_GetSpaceLeftRight(); 00103 } 00104 00105 int mcRadicalHelpers::gui_GetExpOffsetx() const 00106 { 00107 // our exponent is not a real exponent: we use it as an index 00108 return 0; 00109 } 00110 00111 int mcRadicalHelpers::gui_GetVWidth() const 00112 { 00113 return mcMAX(15, gui_GetExpSubSize(TRUE).GetWidth()/4); 00114 } 00115 00116 void mcRadicalHelpers::gui_DoRecalcBaseSize() 00117 { 00118 wxString tmp; 00119 wxScreenDC dc; 00120 00121 // compute size of content 00122 mgui_szBase = data_GetContent().gui_GetSize(); 00123 00124 // update size member (due to the fact that our gui_GetExpOffsetx doesn't return 00125 // the with of the base, we must take in count the size of the exponent, too). 00126 mgui_szBase.SetWidth(mgui_szBase.GetWidth() + mcMAX(gui_GetExpSubSize(TRUE).GetWidth(), 5) + 00127 gui_GetSpaceLeftRight()*2 + gui_GetVWidth() + mcElementHelpers::gui_GetThickness(NULL)); 00128 mgui_szBase.SetHeight(mgui_szBase.GetHeight() + gui_GetSpaceAboveBelow()*2 + 00129 mcElementHelpers::gui_GetThickness(NULL)); 00130 } 00131 00132 void mcRadicalHelpers::gui_DrawContainer(wxDC &hDC, int Offsetx, int Offsety, long flags, const wxPoint &pt) const 00133 { 00134 // set up the pen to use to draw the symbols 00135 int thickness = mcElementHelpers::gui_GetThickness(NULL); 00136 wxPen pen(*wxBLACK, thickness, wxSOLID); 00137 hDC.SetPen(pen); 00138 00139 // | ___________ | y2 00140 // y | exp / | 00141 // | ---- / | 00142 // \ / m_eContent 00143 // \/ 00144 // 00145 // |---|-----| 00146 // w n 00147 // 00148 int y = Offsety+mcMAX(gui_GetExpSubSize(TRUE).GetHeight()+5, 15), 00149 y2 = Offsety+thickness/2+1, 00150 w = Offsetx+mcMAX(gui_GetExpSubSize(TRUE).GetWidth(), 5), 00151 n = gui_GetVWidth(); 00152 00153 // draw the exponent underlining 00154 hDC.DrawLine(Offsetx, y, w+1, y); // the +1 is used to join the two lines 00155 00156 // draw the V 00157 hDC.DrawLine(w, y, w+n/2, Offsety+gui_GetBaseSize().GetHeight()); 00158 hDC.DrawLine(w+n/2+1, Offsety+gui_GetBaseSize().GetHeight(), w+n, y2); 00159 00160 // draw the remaining lines 00161 hDC.DrawLine(w+n-1, y2, Offsetx+gui_GetWidth(), y2); 00162 hDC.DrawLine(Offsetx+gui_GetWidth(), y2, Offsetx+gui_GetWidth(), Offsety+3); 00163 } 00164 /* 00165 int mcRadicalHelpers::gui_BaseMoveCursorUsingPoint(wxDC &dc, const wxPoint &p) 00166 { 00167 // just check if the point is in the 00168 return mcMCR_OKAY; 00169 } 00170 */ 00171 00172 00173 00174 00175 00176 // ---------------------------------------- 00177 // mcRADICALIO 00178 // ---------------------------------------- 00179 00180 wxXml2Node mcRadicalHelpers::io_GetBaseMathML(bool bGetPresentation) const 00181 { 00182 // this is just a fake function: see mcRadicalHelpers::io_GetMathML 00183 return wxXml2EmptyNode; 00184 } 00185 00186 wxXml2Node mcRadicalHelpers::io_GetMathML(bool bGetPresentation) const 00187 { 00188 wxXml2Node p = wxXml2Node(wxXML_ELEMENT_NODE, wxXml2EmptyDoc, wxT("msqrt")); 00189 00190 // do we need to show something else than the standard index "2" 00191 // (which, really, is not shown at all....) ? 00192 if (data_hasProperty(mcEP_HASEXPONENT)) 00193 p.SetName(wxT("mroot")); 00194 00195 // add to the p node, the content 00196 wxXml2Node content(data_GetContent().io_GetMathML(bGetPresentation)); 00197 p.AddChild(content); 00198 00199 // add the index, if necessary 00200 if (data_hasProperty(mcEP_HASEXPONENT)) { 00201 wxXml2Node exp(data_GetExp().io_GetMathML(bGetPresentation)); 00202 p.AddChild(exp); 00203 } 00204 00205 return p; 00206 } 00207 00208 wxString mcRadicalHelpers::io_GetInlinedExpr() const 00209 { 00210 wxString res = sio_strSquareRoot; 00211 bool needidx = FALSE; 00212 00213 if (data_hasProperty(mcEP_HASEXPONENT)) { 00214 res = sio_strGenericRoot; 00215 needidx = TRUE; 00216 } 00217 00218 res += wxT("(") + data_GetContent().io_GetInlinedExpr(); 00219 00220 // do we need to add the index ? 00221 if (needidx) 00222 res += wxT(", ") + data_GetExp().io_GetInlinedExpr(); 00223 00224 res += wxT(")"); 00225 return res; 00226 } 00227 00228 bool mcRadicalHelpers::io_ImportPresentationMathML(wxXml2Node tag, wxString &pErr) 00229 { 00230 return TRUE; 00231 } 00232 00233 bool mcRadicalHelpers::io_ImportBaseInlinedExpr(const wxString &str, int *count, wxString &perr) 00234 { 00235 wxArrayString argarr; 00236 wxString arg(str); 00237 int totallenght; 00238 00239 if (str.StartsWith(sio_strGenericRoot)) { 00240 00241 // set the mcEP_HASEXPONENT property 00242 data_CreateExpSub(TRUE); 00243 totallenght = sio_strGenericRoot.Len(); 00244 00245 } else { 00246 00247 totallenght = sio_strSquareRoot.Len(); 00248 } 00249 00250 // truncate the string to the end of the argument 00251 arg = arg.Right(arg.Len()-totallenght); 00252 wxString idx(arg); 00253 argarr = mcFunctionHelpers::io_ImportArgument(arg, count, perr); 00254 if (argarr.GetCount() == 0) return FALSE; 00255 totallenght += *count; 00256 00257 // by now, process the first arg... 00258 arg = argarr[0]; 00259 00260 // import the 1st arg 00261 if (!data_GetContent().io_ImportInlinedExpr(arg, count, perr)) 00262 return FALSE; 00263 mcASSERT(*count == (int)arg.Len(), wxT("The argument should have been completely imported")); 00264 00265 // get the second argument (if present) 00266 if (argarr.GetCount() > 1) { 00267 00268 if (argarr[1].IsEmpty()) { 00269 00270 // the user should have written something like: ,, 00271 perr = wxT("An empty argument has been found in the token: ") + str; 00272 return FALSE; 00273 } 00274 00275 // import our index as the exponent... 00276 if (!data_GetExp().io_ImportInlinedExpr(argarr[1], count, perr)) 00277 return FALSE; 00278 mcASSERT(*count == (int)argarr[1].Len(), 00279 wxT("The argument should have been completely imported")); 00280 00281 // this should be a generic root ! 00282 00283 } else { 00284 00285 // check if the user called us as a generic or a square root 00286 if (data_hasProperty(mcEP_HASEXPONENT)) 00287 math_GetExp().math_WrapNumber(2.0); 00288 } 00289 00290 *count = totallenght; 00291 00292 return TRUE; 00293 } 00294 00295 00296 00297 00298 // ---------------------------------------- 00299 // mcRADICALMATH 00300 // ---------------------------------------- 00301 00302 mcRealValue mcRadicalHelpers::math_Evaluate() const 00303 { 00304 mcRealValue base = math_EvaluateBase(); 00305 00306 // if we do not have any index, then a 2.0 is the default (sqrt) 00307 mcRealValue idx = 2.0; 00308 00309 if (math_hasIdx()) 00310 idx = math_GetIdx().math_Evaluate(); 00311 00312 // now, just raise the base to the exp... 00313 return base.root(idx); 00314 } 00315 00316 mcMathType mcRadicalHelpers::math_GetBaseMathType() const 00317 { 00318 mcMathType res = mcExpContainerHelpers::math_GetBaseMathType(); 00319 00320 // a radical is another way to express an exp element: 00321 // sqrt(base, idx) = base ^ (1/idx) 00322 00323 // since our idx is the denominator of the exponent, if we contain 00324 // unknowns in our idx, the global data must not be considered 00325 // as polynomial but as rational: unknowns are placed at den... 00326 if (math_hasIdx() && math_GetIdx().math_ContainsUnknowns()) 00327 res.m_tMath1 = mcMTL1_RATIONAL; 00328 00329 return res; 00330 } 00331 00332 mcExpSimRes mcRadicalHelpers::math_SimplifyContents(long flags, mcElement *) 00333 { 00334 // if the contained polynomial cannot simplify to a single 00335 // monomial, then we cannot do any further simplification... 00336 if (!data_GetContent().math_isFactorized()) 00337 return mcESR_DONE; 00338 00339 mcMonomial m = data_GetContent().math_Get(0); 00340 mcASSERT(m.math_GetCount() > 0, wxT("We contain only an empty monomial ?")); 00341 mcElement e = m.math_Get(0); 00342 00343 switch (e.data_GetType()) { 00344 // if the contained polynomial is a perfect power of something 00345 // (and thus it contains only a mcBracket with exponent), 00346 // our work is simple... if it is not, then we can just try 00347 // to bring factor(s) out of the radical since the contents 00348 // should be completely simplified if this function has been 00349 // called (see mcExpContainer::math_SimplifyBase). 00350 case mcET_BRACKET: 00351 { 00352 mcBracket br(e); 00353 mcPolynomial contentexp = br.data_GetExp(); 00354 00355 mcASSERT(!contentexp.math_EvaluatesTo(1.0), 00356 wxT("This mcBracket should have been already simplified...")); 00357 00358 // now, 00359 // 00360 // root(contents^contentexp, idx) = contents^(contentexp/idx) 00361 // 00362 contentexp.math_SimpleDivideBy(math_GetIdx()); 00363 } 00364 break; 00365 00366 case mcET_NUMBER: 00367 00368 // just try to bring something out... 00369 break; 00370 00371 default: 00372 mcASSERT(0, wxT("TODO")); 00373 } 00374 00375 return mcESR_DONE; 00376 } 00377 00378 mcExpSimRes mcRadicalHelpers::math_ExpandContents(long flags, mcElement *) 00379 { 00380 return mcESR_DONE; 00381 } 00382
[ Top ] |