Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Radical.cpp

Go to the documentation of this file.
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 


Documentation generated with Doxygen on Sun Feb 6 17:10:48 2005
Visit MathStudio home page for more info

[ Top ]