[ast] improve display of (complex) polymomials and rationals 42/21142/10
Stéphane MOTTELET [Wed, 27 Nov 2019 15:59:23 +0000 (16:59 +0100)]
--> p=(1+%i+%s)^7
 p  =

 8-8i -56is -(84+84i)s² -140s³ -(70-70i)s⁴ +42is⁵ +(7+7i)s⁶ +s⁷

--> p=1./[%s %s^2; (%s+1+%i)^2 %s^4] + %s+%i
 p  =

           1 +is +s²          1 +is² +s³
           ─────────          ──────────
               s                  s²

   -1 -(2-4i)s +(2+3i)s² +s³  1 +is⁴ +s⁵
   ─────────────────────────  ──────────
        2i +(2+2i)s +s²           s⁴

Change-Id: If3c4cc35cc7f4e02fe48b5d8f8acd07495501147

scilab/modules/ast/includes/types/singlepoly.hxx
scilab/modules/ast/src/cpp/types/polynom.cpp
scilab/modules/ast/src/cpp/types/singlepoly.cpp
scilab/modules/overloading/macros/%r_p.sci
scilab/modules/overloading/macros/%r_string.sci
scilab/modules/string/sci_gateway/cpp/sci_string.cpp

index dec00f5..2000278 100644 (file)
@@ -59,8 +59,7 @@ public :
     bool                    evaluate(double _dblInR, double _dblInI, double *_pdblOutR, double *_pdblOutI);
     void                    updateRank(void);
 
-    void                    toStringReal(const std::wstring& _szVar, std::list<std::wstring>* _pListCoef);
-    void                    toStringImg(const std::wstring& _szVar, std::list<std::wstring>* _pListCoef);
+    void                    toStringRealImg(const std::wstring& _szVar, std::list<std::wstring>* _pListCoef, int iLineLen);
 
     bool                    toString(std::wostringstream& ostr) override;
 
@@ -88,7 +87,7 @@ protected :
     }
 
 private :
-    void                    toStringInternal(double *_pdblVal, const std::wstring& _szVar, std::list<std::wstring>* _pListCoef);
+    void                    toStringInternal(double *_pdblVal, double *_pdblImg, const std::wstring& _szVar, std::list<std::wstring>* _pListCoef, int iLineLen);
 
 };
 
index 4f003eb..1a85dc5 100644 (file)
@@ -480,25 +480,9 @@ Polynom* Polynom::setCoef(Double *_pCoef)
 
 bool Polynom::subMatrixToString(std::wostringstream& ostr, int* _piDims, int _iDims)
 {
-    std::wostringstream osExp;
-    std::wostringstream osPoly;
-
-    std::list<std::wstring>::const_iterator it_Exp;
-    std::list<std::wstring>::const_iterator it_Coef;
-    std::list<std::wstring> listExpR, listWstPoly, listExpI, listCoefI;
 
-    //Matrix
-    if (isComplex())
-    {
-        ostr << L"Real part" << std::endl << std::endl;
-        ostr << getMatrixString(_piDims, _iDims, false);
-        ostr << L"Imaginary part" << std::endl << std::endl;
-        ostr << getMatrixString(_piDims, _iDims, true);
-    }
-    else
-    {
-        ostr << getMatrixString(_piDims, _iDims, false);
-    }
+    ostr << getMatrixString(_piDims, _iDims, false);
+    
     return true;
 }
 
@@ -509,7 +493,6 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
     std::wostringstream ostr;
     std::wostringstream osPoly;
 
-    std::list<std::wstring>::const_iterator it_Coef;
     std::list<std::wstring> listWstPoly;
 
     int iLen        = 0;
@@ -528,15 +511,8 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
             _piDims[0] = iRows1;
             _piDims[1] = iCols1;
             int iPos = getIndex(_piDims);
-            if (_bComplex)
-            {
-                get(iPos)->toStringImg(getVariableName(), &listWstPoly);
-            }
-            else
-            {
-                get(iPos)->toStringReal(getVariableName(), &listWstPoly);
-            }
-
+            get(iPos)->toStringRealImg(getVariableName(), &listWstPoly, iLineLen);
+            
             for (auto it : listWstPoly)
             {
                 iLength += static_cast<int>(it.size());
@@ -546,7 +522,7 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
         }
 
         //We know the length of the column
-        if (static_cast<int>(iLen + piMaxLen[iCols1]) >= iLineLen && iLen != 0)
+        if (static_cast<int>(iLen + piMaxLen[iCols1]) + 2 >= iLineLen && iLen != 0)
         {
             //if the max length exceeded
             std::wostringstream ostemp;
@@ -560,14 +536,7 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
                     _piDims[1] = iCols2;
 
                     int iPos = getIndex(_piDims);
-                    if (_bComplex)
-                    {
-                        get(iPos)->toStringImg(getVariableName(),  &listWstPoly);
-                    }
-                    else
-                    {
-                        get(iPos)->toStringReal(getVariableName(),  &listWstPoly);
-                    }
+                    get(iPos)->toStringRealImg(getVariableName(),  &listWstPoly, iLineLen);
 
                     if (listWstPoly.size() > 1)
                     {
@@ -579,7 +548,7 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
                     }
                     else
                     {
-                        osPoly << listWstPoly.front();
+                        osPoly << L"  " << listWstPoly.front();
                         addSpaces(&osPoly, piMaxLen[iCols2] - static_cast<int>(listWstPoly.front().size()));
                         bMultiLine = false;
                     }
@@ -622,14 +591,7 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
             _piDims[1] = iCols2;
 
             int iPos = getIndex(_piDims);
-            if (_bComplex)
-            {
-                get(iPos)->toStringImg(getVariableName(), &listWstPoly);
-            }
-            else
-            {
-                get(iPos)->toStringReal(getVariableName(), &listWstPoly);
-            }
+            get(iPos)->toStringRealImg(getVariableName(), &listWstPoly, iLineLen);
 
             if (listWstPoly.size() > 1)
             {
@@ -640,7 +602,7 @@ std::wstring Polynom::getMatrixString(int* _piDims, int /*_iDims*/, bool _bCompl
             }
             else
             {
-                osPoly << listWstPoly.front();
+                osPoly << L"  " << listWstPoly.front();
                 addSpaces(&osPoly, piMaxLen[iCols2] - static_cast<int>(listWstPoly.front().size()));
             }
             listWstPoly.clear();
index 04a15cf..9a3b39a 100644 (file)
@@ -25,6 +25,7 @@ extern "C"
 #include "log.h"
 #include "exp.h"
 #include "elem_common.h"
+#include "sciprint.h"
 }
 
 namespace types
@@ -334,20 +335,9 @@ bool SinglePoly::toString(std::wostringstream& ostr)
     return true;
 }
 
-void SinglePoly::toStringReal(const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly)
+void SinglePoly::toStringRealImg(const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly, int iLineLen)
 {
-    toStringInternal(m_pRealData, _szVar, _pListWstPoly);
-}
-
-void SinglePoly::toStringImg(const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly)
-{
-    if (isComplex() == false)
-    {
-        _pListWstPoly->clear();
-        return;
-    }
-
-    toStringInternal(m_pImgData, _szVar, _pListWstPoly);
+    toStringInternal(m_pRealData, m_pImgData, _szVar, _pListWstPoly, iLineLen);
 }
 
 bool SinglePoly::subMatrixToString(std::wostringstream& /*ostr*/, int* /*_piDims*/, int /*_iDims*/)
@@ -355,26 +345,29 @@ bool SinglePoly::subMatrixToString(std::wostringstream& /*ostr*/, int* /*_piDims
     return false;
 }
 
-void SinglePoly::toStringInternal(double *_pdblVal, const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly)
+void SinglePoly::toStringInternal(double *_pdblR, double *_pdblI, const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly, int iLineLen)
 {
-    int iLineLen = ConfigVariable::getConsoleWidth();
+    int k;
+    int iLen = 0;
+    int iLastFlush = 2;
+    int iParenthLen = 2;
 
     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" ";
+//    ostemp << L" ";
 
-    int k;
-    int iLen = 0;
-    int iLastFlush = 2;
     for (int i = 0 ; i < m_iSize ; i++)
     {
-        if (_pdblVal[i] != 0)
+        double dblR = _pdblR[i];
+        double dblI = _pdblI == NULL ? 0 : _pdblI[i];    
+        
+        if (dblR != 0 && dblI == 0)
         {
             DoubleFormat df;
-            getDoubleFormat(_pdblVal[i], &df);
+            getDoubleFormat(dblR, &df);
 
             if (iLen + df.iWidth + df.iSignLen >= iLineLen - 1)
             {
@@ -387,22 +380,84 @@ void SinglePoly::toStringInternal(double *_pdblVal, const std::wstring& _szVar,
             // 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 = bFirst == false;
+            df.bPrintPlusSign = ! bFirst;
+            df.bPaddSign = ! bFirst;
+            df.bPrintBlank = false;
             df.bPrintOne = i == 0;
+            addDoubleValue(&ostemp, dblR, &df);
+        }
+        else if (dblR != 0 || dblI != 0)
+        {
+            DoubleFormat dfR, dfI;
+            dfR.bPrintPoint = dfR.bExp;
+            dfR.bPrintBlank = false;
+            dfR.bPrintPlusSign = false;
+            dfR.bPaddSign = false;             
+            dfI.bPrintPoint = dfI.bExp;
+            dfI.bPrintBlank = false;
+            dfI.bPaddSign = true;             
+            dfI.bPrintOne = false;
+            if (dblR != 0)
+             {
+                 getDoubleFormat(dblR, &dfR);
+                 dfR.bPaddSign = false;
+                 dfI.bPrintPlusSign = true;
+                 iLen += (i!= 0 ? iParenthLen : 0);
+             }
+             else
+             {
+                 dfI.bPrintPlusSign = ! bFirst;
+                 dfI.bPaddSign = ! bFirst;
+             }
+             getDoubleFormat(dblI, &dfI);
+
+             if (iLen + dfR.iWidth + dfR.iSignLen + dfI.iWidth + dfI.iSignLen + _szVar.length() + iExponentsDigits.size() >= iLineLen - 1)
+             {
+                 iLastFlush = i;
+                 _pListWstPoly->push_back(ostemp.str());
+                 ostemp.str(L""); //reset stream
+                 addSpaces(&ostemp, 1); //take from scilab ... why not ...
+             }
+
+             if (dblR != 0)
+             {
+                 if (bFirst == false)
+                 {
+                     if (dblR > 0)
+                     {
+                         ostemp << L"+";     
+                     }
+                     else
+                     {
+                         dblR = -dblR;
+                         dblI = -dblI;
+                         ostemp << L"-"; 
+                     }   
+                 }
+                 if (i != 0)
+                 {
+                     ostemp << L"(";
+                 }
+                 addDoubleValue(&ostemp, dblR, &dfR);
+             }
+             addDoubleValue(&ostemp, dblI, &dfI);
+             ostemp << L"i";
+             
+             if (dblR != 0 & i != 0)
+             {
+                 ostemp << L")";
+             }
+        }
+        
+        if (dblR != 0 || dblI != 0)
+        {            
             bFirst = false;
-            addDoubleValue(&ostemp, _pdblVal[i], &df);
-            
-            if (i == 0)
-            {
-                iLen = static_cast<int>(ostemp.str().size());
-            }
-            else if (i == 1)
+            if (i == 1)
             {
                 // add polynomial variable
                 ostemp << _szVar;
-                iLen = static_cast<int>(ostemp.str().size());
             }
-            else
+            else if (i != 0)
             {
                 // add polynomial variable and exponent
                 ostemp << _szVar;
@@ -410,8 +465,12 @@ void SinglePoly::toStringInternal(double *_pdblVal, const std::wstring& _szVar,
                 {
                     ostemp << strExponentDigits[*it];
                 }
-                iLen = static_cast<int>(ostemp.str().size());            
-            }            
+            }
+            if (i < m_iSize-1)
+            {
+                ostemp << L" ";
+            }
+            iLen = static_cast<int>(ostemp.str().size());
         }
 
         for (k=0; k < iExponentsDigits.size() && iExponentsDigits[k] == 9; k++)
@@ -427,9 +486,9 @@ void SinglePoly::toStringInternal(double *_pdblVal, const std::wstring& _szVar,
 
     if (iLastFlush != 0)
     {
-        if (ostemp.str() == L" ")
+        if (ostemp.str() == L"")
         {
-            ostemp << L"  0";
+            ostemp << L"0";
         }
 
         _pListWstPoly->push_back(ostemp.str());
index b9da61f..c8fe5f5 100644 (file)
@@ -57,9 +57,13 @@ function %r_p(h)
                 for k=1:last
                     txtr=txtr+part(blank(ones(height(l),1)),1:2)
                     tlk=T(l+(k0+k-1)*m)
+                    iPad = (width(k)-max(length(tlk)))/2;
+                    if iPad>=1
+                        tlk=part(blank,1:iPad)+tlk;
+                    end
                     txtr=txtr+[part(tlk,1:width(k));emptystr(height(l)-size(tlk,1),1)]
                 end
-                txt=[txt;txtr]
+                txt=[txt;ascii(13);txtr]
             end
             // add matrix delimiter and columns title and display
             nt=size(txt,1)
@@ -91,83 +95,13 @@ function %r_p(h)
 
 endfunction
 
-function txt=p2str(p)
-    //form display of a single polynomial with complex coefficients
-    lparen="("
-    rparen=")"
-    blank=" "
-    if type(p)==1 then p=poly(p,"s","c"),end
-    d=degree(p)
-    v=stripblanks(varn(p))
-
-    c=strsubst(string(coeff(p)),"%i","i")
-    // find coefficients with displays as "0" (deleted later)
-    kz=find(c=="0")
-    // find coefficients with displays as "1"
-    k1=find(c=="1");if k1(1)==1 then k1(1)=[],end
-    if k1<>[] then c(k1)=emptystr(1,size(k1,"*")),end
-    // find coefficients with displays as "-1"
-    k1=find(c=="-1");if k1(1)==1 then k1(1)=[],end
-    if k1<>[] then c(k1)="-",end
-    // find coefficients with real AND imaginary part (to be parenthezied)
-    kc=find(imag(coeff(p))<>0&real(coeff(p))<>0)
-    w=ones(1,size(kc,"*"))
-    if kc<>[] then c(kc)=lparen(w)+c(kc)+rparen(w),end
-    // add formal variable name
-    c=c+[emptystr(),v(ones(1:d))]
-
-    // form exponents
-    expo1=[" "," ",string(2:d)]
-
-    //delete coeffiecients and exponents corresponding to "0"s
-    c(kz)=[]
-    expo1(kz)=[]
-    if c==[] then
-        c="0"
-        expo1=emptystr()
-    end
-
-    // change coefficients sign display and adjust length of exponents
-    le=0
-    expo=emptystr(c)
-    for kc=1:size(c,"*")
-        if kc>1 then
-            if part(c(kc),1)<>"-" then
-                c(kc)=" + "+c(kc),
-            else
-                c(kc)=" - "+part(c(kc),2:length(c(kc)))
-            end
-        end
-        expo(kc)=part(blank,ones(1,length(c(kc))-le))
-        le=length(expo1(kc))
-    end
-    expo=expo+expo1(1:size(c,"*"))
-
-    //Handle long lines
-    ll=lines()
-    nn=size(expo,"*")
-    txt=[]
-    count=0
-    while %t
-        L=cumsum(length(expo))
-        last=find(L<ll(1)-3);last=last($)
-        txt=[txt;
-        part(blank,ones(1,count))+strcat(expo(1:last));
-        strcat(c(1:last))]
-        expo(1:last)=[]
-        c(1:last)=[]
-        if c==[] then break,end
-        count=count+1
-    end
-
-endfunction
 function txt=r2str(h)
     //form display of a single rational with complex coefficients
-    dash="-"
+    dash=ascii([226 148 128]);
     blank=" "
 
-    t1=p2str(h("num")) //display of numerator
-    t2=p2str(h("den")) //display of denominator
+    t1=string(h("num")) //display of numerator
+    t2=string(h("den")) //display of denominator
 
     //add fraction bar and center
     l1=max(length(t1))
index 0138e1d..11635da 100644 (file)
@@ -1,5 +1,6 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) 2016 - Samuel GOUGEON
+// Copyright (C) 2019 - Stéphane MOTTELET
 //
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
 //
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
+
 function txt = %r_string(r)
     // string output of any array of rationals, of any number of dimensions (even>2)
     //
     N = string(r.num(:))
     D = string(r.den(:))
     nr = size(r,"*")
-    i = 1:2:2*nr
+    i = 1:nr
     lengthI = max([length(N(i)) length(D(i))],"c")
-    hruleMax = part("-",ones(1:max(lengthI)))
+    hruleMax = part(ascii([226 148 128]),ones(1:max(lengthI)))
     hrules = strncpy(emptystr(nr,1)+hruleMax,lengthI)
-    txt = emptystr(nr*5,1);
-    j = 1:5:5*nr
-    txt(j)   = N(i)    // Exponents of numerator
-    txt(j+1) = N(i+1)  // Coefficients of numerator
-    txt(j+2) = hrules  // -------------------------
-    txt(j+3) = D(i)    // Exponents of denominator
-    txt(j+4) = D(i+1)  // Coefficients of denominator
-
-    // Centering the shortest part num or den on the other:
-    // justify(,"c") can't be used on exponents rows due to their leading blanks
-    txt = matrix(txt,5,-1)
-    [lmin, irmin] = min(length(txt),"r")
-    [lmax, irmax] = max(length(txt),"r")
-    leftpaddlength = floor((lmax-lmin)/2)
-    hpaddMax = part(" ", ones(1:max(leftpaddlength)))
-    padding = strncpy(emptystr(1,nr)+hpaddMax, leftpaddlength)
-    k = irmin<3  //  columns are %T where the num is the shortest
-    txt(1,k)  = padding(k)  + txt(1,k)
-    txt(2,k)  = padding(k)  + txt(2,k)
-    txt(4,~k) = padding(~k) + txt(4,~k)
-    txt(5,~k) = padding(~k) + txt(5,~k)
+    txt = emptystr(nr*3,1);
+    j = 1:3:3*nr
+    txt(j)   = N(i)    // numerator
+    txt(j+1) = hrules  // ----------
+    txt(j+2) = D(i)    // denominator
 
-    // We reshape the result
+    // We reshape and justify the result
     s = size(r)
     s(1) = -1
-    txt = matrix(txt,s)
+    txt = justify(matrix(txt,s),"c")
 endfunction
index c97dea8..e797a4d 100644 (file)
@@ -31,6 +31,7 @@
 #include "sparse.hxx"
 #include "int.hxx"
 #include "implicitlist.hxx"
+#include "polynom.hxx"
 
 extern "C"
 {
@@ -312,6 +313,26 @@ types::Function::ReturnValue implicitListString(types::ImplicitList* pIL, types:
     return types::Function::OK;
 }
 
+types::Function::ReturnValue PolynomString(types::Polynom* pPol, types::typed_list &out)
+{
+    int iDims = pPol->getDims();
+    int* piDimsArray = pPol->getDimsArray();
+    types::String *pStr = new types::String(iDims, piDimsArray);
+    std::list<std::wstring> listWstPoly;
+
+    for (int iPos=0; iPos < pPol->getSize(); iPos++)
+    {
+        pPol->get(iPos)->toStringRealImg(pPol->getVariableName(), &listWstPoly, INT_MAX);
+        pStr->set(iPos,listWstPoly.front().c_str());
+        listWstPoly.clear();
+    }
+
+    out.push_back(pStr);
+    return types::Function::OK;
+}
+
+
+
 types::Function::ReturnValue sci_string(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
     if (in.size() != 1)
@@ -480,7 +501,6 @@ types::Function::ReturnValue sci_string(types::typed_list &in, int _iRetCount, t
         }
         case types::InternalType::ScilabTList :
         case types::InternalType::ScilabMList :
-        case types::InternalType::ScilabPolynom :
         case types::InternalType::ScilabHandle :
         {
             std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_string";
@@ -516,6 +536,12 @@ types::Function::ReturnValue sci_string(types::typed_list &in, int _iRetCount, t
             out.push_back(new types::String(L""));
             break;
         }
+        case types::InternalType::ScilabPolynom :
+        {
+            return PolynomString(in[0]->getAs<types::Polynom>(), out);
+            break;            
+        }
+        
         default:
         {
             std::wostringstream ostr;