[ast] improved polynomial display with unicode superscripts
[scilab.git] / scilab / modules / ast / src / cpp / types / singlepoly.cpp
index 8e921d6..04a15cf 100644 (file)
@@ -2,19 +2,23 @@
 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
 *
-*  This file must be used under the terms of the CeCILL.
-*  This source file is licensed as described in the file COPYING, which
-*  you should have received as part of this distribution.  The terms
-*  are also available at
-*  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ * Copyright (C) 2012 - 2016 - Scilab Enterprises
+ *
+ * This file is hereby licensed under the terms of the GNU GPL v2.0,
+ * pursuant to article 5.3.4 of the CeCILL v.2.1.
+ * This file was originally licensed under the terms of the CeCILL v2.1,
+ * and continues to be available under such terms.
+ * For more information, see the COPYING file which you should have received
+ * along with this program.
 *
 */
 #include <sstream>
-#include <math.h>
+#include <cmath>
 #include "singlepoly.hxx"
 #include "double.hxx"
 #include "tostring_common.hxx"
 #include "configvariable.hxx"
+#include "scilabWrite.hxx"
 
 extern "C"
 {
@@ -23,8 +27,6 @@ extern "C"
 #include "elem_common.h"
 }
 
-using namespace std;
-
 namespace types
 {
 SinglePoly::SinglePoly()
@@ -33,23 +35,35 @@ SinglePoly::SinglePoly()
     int piDims[2] = {1, 1};
     create(piDims, 2, &pdblCoefR, NULL);
     pdblCoefR[0] = 0;
+#ifndef NDEBUG
+    Inspector::addItem(this);
+#endif
 }
 
 SinglePoly::SinglePoly(double** _pdblCoefR, int _iRank)
 {
     int piDims[2] = {_iRank + 1, 1};
     create(piDims, 2, _pdblCoefR, NULL);
+#ifndef NDEBUG
+    Inspector::addItem(this);
+#endif
 }
 
 SinglePoly::SinglePoly(double** _pdblCoefR, double** _pdblCoefI, int _iRank)
 {
     int piDims[2] = {_iRank + 1, 1};
     create(piDims, 2, _pdblCoefR, _pdblCoefI);
+#ifndef NDEBUG
+    Inspector::addItem(this);
+#endif
 }
 
 SinglePoly::~SinglePoly()
 {
     deleteAll();
+#ifndef NDEBUG
+    Inspector::removeItem(this);
+#endif
 }
 
 void SinglePoly::deleteAll()
@@ -73,7 +87,7 @@ double SinglePoly::getNullValue()
     return 0;
 }
 
-SinglePoly* SinglePoly::createEmpty(int _iDims, int* _piDims, bool _bComplex)
+SinglePoly* SinglePoly::createEmpty(int /*_iDims*/, int* _piDims, bool _bComplex)
 {
     double* pdblData = NULL;
     SinglePoly* pSP = new SinglePoly(&pdblData, _piDims[0] - 1);
@@ -92,23 +106,21 @@ double* SinglePoly::allocData(int _iSize)
             m_pRealData = NULL;
             m_pImgData = NULL;
             char message[bsiz];
-            sprintf(message, _("Can not allocate negative size (%d).\n"),  _iSize);
-            ast::ScilabError se(message);
-            se.SetErrorNumber(999);
-            throw (se);
+            os_sprintf(message, _("Can not allocate negative size (%d).\n"),  _iSize);
+            throw ast::InternalError(message);
         }
         else
         {
             pDbl = new double[_iSize];
         }
     }
-    catch (std::bad_alloc &e)
+    catch (std::bad_alloc &/*e*/)
     {
         char message[bsiz];
-        sprintf(message, _("Can not allocate %.2f MB memory.\n"),  (double) (_iSize * sizeof(double)) / 1.e6);
-        ast::ScilabError se(message);
-        se.SetErrorNumber(999);
-        throw (se);
+        char byteString[9];
+        humanReadableByteCount(((size_t) m_iSize) * sizeof(double), byteString);
+        os_sprintf(message, _("Can not allocate %s memory.\n"), byteString);
+        throw ast::InternalError(message);
     }
 
     return pDbl;
@@ -124,6 +136,11 @@ int SinglePoly::getRank()
     return m_iSize - 1;
 }
 
+double SinglePoly::getDegree()
+{
+    return m_iSize == 1 && m_pRealData[0] == 0 && (m_pImgData == NULL || m_pImgData[0] == 0) ? -INFINITY : m_iSize - 1;
+}
+
 bool SinglePoly::setRank(int _iRank, bool bSave)
 {
     double *pR = NULL;
@@ -133,7 +150,7 @@ bool SinglePoly::setRank(int _iRank, bool bSave)
         if (getRank() != _iRank)
         {
             int piDims[2] = {_iRank + 1, 1};
-            if (m_pImgData == false)
+            if (m_pImgData == NULL)
             {
                 deleteAll();
                 create(piDims, 2, &pR, NULL);
@@ -156,7 +173,7 @@ bool SinglePoly::setRank(int _iRank, bool bSave)
         int iMinSize = Min(m_iSize, _iRank + 1);
         int piDims[2] = {_iRank + 1, 1};
 
-        if (m_pImgData == false)
+        if (m_pImgData == NULL)
         {
             create(piDims, 2, &pR, NULL);
         }
@@ -222,7 +239,7 @@ bool SinglePoly::setCoef(Double* _pdblCoefR)
     return setCoef(pInR, pInI);
 }
 
-bool SinglePoly::setCoef(double* _pdblCoefR, double* _pdblCoefI)
+bool SinglePoly::setCoef(const double* _pdblCoefR, const double* _pdblCoefI)
 {
     if (_pdblCoefI != NULL && isComplex() == false)
     {
@@ -259,15 +276,15 @@ bool SinglePoly::evaluate(double _dblInR, double _dblInI, double *_pdblOutR, dou
     for (int i = 0 ; i < m_iSize ; i++)
     {
         //real part
-        *_pdblOutR += m_pRealData[i] * pow(_dblInR, i);
+        *_pdblOutR += m_pRealData[i] * std::pow(_dblInR, i);
         //only if variable is complex
         if (isComplex())
         {
-            *_pdblOutR -= m_pImgData[i] * pow(_dblInI, i);
+            *_pdblOutR -= m_pImgData[i] * std::pow(_dblInI, i);
             //img part
-            *_pdblOutI += m_pRealData[i] * pow(_dblInR, i);
+            *_pdblOutI += m_pRealData[i] * std::pow(_dblInR, i);
         }
-        *_pdblOutI += m_pRealData[i] * pow(_dblInI, i);
+        *_pdblOutI += m_pRealData[i] * std::pow(_dblInI, i);
     }
 
     return true;
@@ -275,13 +292,12 @@ bool SinglePoly::evaluate(double _dblInR, double _dblInI, double *_pdblOutR, dou
 
 void SinglePoly::updateRank(void)
 {
-    double dblEps = getRelativeMachinePrecision();
     int iNewRank = getRank();
     if (m_pImgData)
     {
         for (int i = getRank(); i > 0 ; i--)
         {
-            if (fabs(m_pRealData[i]) <= dblEps && abs(m_pImgData[i]) <= dblEps)
+            if (std::fabs(m_pRealData[i]) == 0.0 && std::fabs(m_pImgData[i]) == 0.0)
             {
                 iNewRank--;
             }
@@ -295,7 +311,7 @@ void SinglePoly::updateRank(void)
     {
         for (int i = getRank(); i > 0 ; i--)
         {
-            if (fabs(m_pRealData[i]) <= dblEps)
+            if (std::fabs(m_pRealData[i]) == 0.0)
             {
                 iNewRank--;
             }
@@ -318,129 +334,107 @@ bool SinglePoly::toString(std::wostringstream& ostr)
     return true;
 }
 
-void SinglePoly::toStringReal(wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
+void SinglePoly::toStringReal(const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly)
 {
-    toStringInternal(m_pRealData, _szVar, _pListExp, _pListCoef);
+    toStringInternal(m_pRealData, _szVar, _pListWstPoly);
 }
 
-void SinglePoly::toStringImg(wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
+void SinglePoly::toStringImg(const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly)
 {
     if (isComplex() == false)
     {
-        _pListExp->clear();
-        _pListCoef->clear();
+        _pListWstPoly->clear();
         return;
     }
 
-    toStringInternal(m_pImgData, _szVar, _pListExp, _pListCoef);
+    toStringInternal(m_pImgData, _szVar, _pListWstPoly);
 }
 
-bool SinglePoly::subMatrixToString(wostringstream& ostr, int* _piDims, int _iDims)
+bool SinglePoly::subMatrixToString(std::wostringstream& /*ostr*/, int* /*_piDims*/, int /*_iDims*/)
 {
     return false;
 }
 
-void SinglePoly::toStringInternal(double *_pdblVal, wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
+void SinglePoly::toStringInternal(double *_pdblVal, const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly)
 {
-    int iPrecision = ConfigVariable::getFormatSize();
     int iLineLen = ConfigVariable::getConsoleWidth();
 
-    wostringstream ostemp;
-    wostringstream ostemp2;
+    std::wstring strExponentDigits (L"\u2070\u00B9\u00B2\u00B3\u2074\u2075\u2076\u2077\u2078\u2079");
+    std::vector<int> iExponentsDigits = {0};
+    std::wostringstream ostemp;
+    bool bFirst = true;
 
-    ostemp << L"  ";
-    ostemp2 << L"";
-
-    //to add exponant value a the good place
-    int *piIndexExp = new int[m_iSize];
+    ostemp << L" ";
 
+    int k;
     int iLen = 0;
     int iLastFlush = 2;
     for (int i = 0 ; i < m_iSize ; i++)
     {
-        piIndexExp[i] = 0;
-        if (isRealZero(_pdblVal[i]) == false)
+        if (_pdblVal[i] != 0)
         {
             DoubleFormat df;
             getDoubleFormat(_pdblVal[i], &df);
 
-            if (iLen + df.iWidth + 2 >= iLineLen)
+            if (iLen + df.iWidth + df.iSignLen >= iLineLen - 1)
             {
-                //flush
-                for (int j = iLastFlush ; j < i ; j++)
-                {
-                    if (piIndexExp[j] == 0)
-                    {
-                        continue;
-                    }
-
-                    addSpaces(&ostemp2, piIndexExp[j] - static_cast<int>(ostemp2.str().size()));
-                    if (isRealZero(_pdblVal[j]) == false)
-                    {
-                        ostemp2 << j;
-                    }
-                }
                 iLastFlush = i;
-                _pListExp->push_back(ostemp2.str());
-                ostemp2.str(L""); //reset stream
-                addSpaces(&ostemp2, 12); //take from scilab ... why not ...
-
-                _pListCoef->push_back(ostemp.str());
+                _pListWstPoly->push_back(ostemp.str());
                 ostemp.str(L""); //reset stream
-                addSpaces(&ostemp, 12); //take from scilab ... why not ...
+                addSpaces(&ostemp, 1); //take from scilab ... why not ...
             }
 
-            bool bFirst = ostemp.str().size() == 2;
-
             // In scientific notation case bExp == true, so we have to print point (2.000D+10s)
             // In other case don't print point (2s)
             df.bPrintPoint = df.bExp;
-            df.bPrintPlusSign = ostemp.str().size() != 2;
+            df.bPrintPlusSign = bFirst == false;
             df.bPrintOne = i == 0;
+            bFirst = false;
             addDoubleValue(&ostemp, _pdblVal[i], &df);
-
-            if (i != 0)
+            
+            if (i == 0)
             {
-                ostemp << _szVar;
-                piIndexExp[i] = static_cast<int>(ostemp.str().size());
+                iLen = static_cast<int>(ostemp.str().size());
             }
-            ostemp << L" ";
-            iLen = static_cast<int>(ostemp.str().size());
-        }
-    }
-
-    if (iLastFlush != 0)
-    {
-        for (int j = iLastFlush ; j < m_iSize ; j++)
-        {
-            if (piIndexExp[j] == 0)
+            else if (i == 1)
             {
-                continue;
+                // add polynomial variable
+                ostemp << _szVar;
+                iLen = static_cast<int>(ostemp.str().size());
             }
-
-            addSpaces(&ostemp2, piIndexExp[j] - static_cast<int>(ostemp2.str().size()));
-            if (isRealZero(_pdblVal[j]) == false)
+            else
             {
-                ostemp2 << j;
-            }
+                // add polynomial variable and exponent
+                ostemp << _szVar;
+                for (auto it = iExponentsDigits.rbegin(); it != iExponentsDigits.rend(); ++it)
+                {
+                    ostemp << strExponentDigits[*it];
+                }
+                iLen = static_cast<int>(ostemp.str().size());            
+            }            
         }
 
-        if (ostemp.str() == L"  ")
+        for (k=0; k < iExponentsDigits.size() && iExponentsDigits[k] == 9; k++)
         {
-            ostemp << L"  0";
-            addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
+            iExponentsDigits[k] = 0;
+        }
+        if (k == iExponentsDigits.size())
+        {
+            iExponentsDigits.push_back(0);
         }
+        iExponentsDigits[k]++;
+    }
 
-        if (ostemp2.str() == L"")
+    if (iLastFlush != 0)
+    {
+        if (ostemp.str() == L" ")
         {
-            addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
+            ostemp << L"  0";
         }
 
-        _pListExp->push_back(ostemp2.str());
-        _pListCoef->push_back(ostemp.str());
+        _pListWstPoly->push_back(ostemp.str());
     }
 
-    delete[] piIndexExp;
     return;
 }
 
@@ -531,7 +525,6 @@ SinglePoly* SinglePoly::clone()
 
 SinglePoly* SinglePoly::conjugate()
 {
-    SinglePoly* pPoly = NULL;
     if (isComplex())
     {
         double *pR = NULL;