[ast] fix polynom display after 0000af49
[scilab.git] / scilab / modules / ast / src / cpp / types / singlepoly.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15 #include <sstream>
16 #include <cmath>
17 #include "singlepoly.hxx"
18 #include "double.hxx"
19 #include "tostring_common.hxx"
20 #include "configvariable.hxx"
21 #include "scilabWrite.hxx"
22
23 extern "C"
24 {
25 #include "log.h"
26 #include "exp.h"
27 #include "elem_common.h"
28 #include "sciprint.h"
29 }
30
31 namespace types
32 {
33 SinglePoly::SinglePoly()
34 {
35     double* pdblCoefR = NULL;
36     int piDims[2] = {1, 1};
37     create(piDims, 2, &pdblCoefR, NULL);
38     pdblCoefR[0] = 0;
39 #ifndef NDEBUG
40     Inspector::addItem(this);
41 #endif
42 }
43
44 SinglePoly::SinglePoly(double** _pdblCoefR, int _iRank)
45 {
46     int piDims[2] = {_iRank + 1, 1};
47     create(piDims, 2, _pdblCoefR, NULL);
48 #ifndef NDEBUG
49     Inspector::addItem(this);
50 #endif
51 }
52
53 SinglePoly::SinglePoly(double** _pdblCoefR, double** _pdblCoefI, int _iRank)
54 {
55     int piDims[2] = {_iRank + 1, 1};
56     create(piDims, 2, _pdblCoefR, _pdblCoefI);
57 #ifndef NDEBUG
58     Inspector::addItem(this);
59 #endif
60 }
61
62 SinglePoly::~SinglePoly()
63 {
64     deleteAll();
65 #ifndef NDEBUG
66     Inspector::removeItem(this);
67 #endif
68 }
69
70 void SinglePoly::deleteAll()
71 {
72     delete[] m_pRealData;
73     m_pRealData = NULL;
74     deleteImg();
75 }
76
77 void SinglePoly::deleteImg()
78 {
79     if (m_pImgData != NULL)
80     {
81         delete[] m_pImgData;
82         m_pImgData = NULL;
83     }
84 }
85
86 double SinglePoly::getNullValue()
87 {
88     return 0;
89 }
90
91 SinglePoly* SinglePoly::createEmpty(int /*_iDims*/, int* _piDims, bool _bComplex)
92 {
93     double* pdblData = NULL;
94     SinglePoly* pSP = new SinglePoly(&pdblData, _piDims[0] - 1);
95     pSP->setComplex(_bComplex);
96
97     return pSP;
98 }
99
100 double* SinglePoly::allocData(int _iSize)
101 {
102     double* pDbl = NULL;
103     try
104     {
105         if (_iSize < 0)
106         {
107             m_pRealData = NULL;
108             m_pImgData = NULL;
109             char message[bsiz];
110             os_sprintf(message, _("Can not allocate negative size (%d).\n"),  _iSize);
111             throw ast::InternalError(message);
112         }
113         else
114         {
115             pDbl = new double[_iSize];
116         }
117     }
118     catch (std::bad_alloc &/*e*/)
119     {
120         char message[bsiz];
121         char byteString[9];
122         humanReadableByteCount(((size_t) m_iSize) * sizeof(double), byteString);
123         os_sprintf(message, _("Can not allocate %s memory.\n"), byteString);
124         throw ast::InternalError(message);
125     }
126
127     return pDbl;
128 }
129
130 bool SinglePoly::hasComplexCoef()
131 {
132     if (m_pImgData)
133     {
134         for (int i = 0; i < m_iSize; ++i)
135         {
136             if (m_pImgData[i] != 0)
137             {
138                 return true;
139             }
140         }
141     }
142
143     return false;
144 }
145
146 double SinglePoly::copyValue(double _dblData)
147 {
148     return _dblData;
149 }
150
151 int SinglePoly::getRank()
152 {
153     return m_iSize - 1;
154 }
155
156 double SinglePoly::getDegree()
157 {
158     return m_iSize == 1 && m_pRealData[0] == 0 && (m_pImgData == NULL || m_pImgData[0] == 0) ? -INFINITY : m_iSize - 1;
159 }
160
161 bool SinglePoly::setRank(int _iRank, bool bSave)
162 {
163     double *pR = NULL;
164     double *pI = NULL;
165     if (bSave == false)
166     {
167         if (getRank() != _iRank)
168         {
169             int piDims[2] = {_iRank + 1, 1};
170             if (m_pImgData == NULL)
171             {
172                 deleteAll();
173                 create(piDims, 2, &pR, NULL);
174             }
175             else
176             {
177                 deleteAll();
178                 create(piDims, 2, &pR, &pI);
179             }
180
181             return true;
182         }
183
184         return true;
185     }
186     else
187     {
188         double* pdblOldReal = m_pRealData;
189         double* pdblOldImg  = m_pImgData;
190         int iMinSize = Min(m_iSize, _iRank + 1);
191         int piDims[2] = {_iRank + 1, 1};
192
193         if (m_pImgData == NULL)
194         {
195             create(piDims, 2, &pR, NULL);
196         }
197         else
198         {
199             create(piDims, 2, &pR, &pI);
200             memcpy(m_pImgData, pdblOldImg, iMinSize * sizeof(double));
201         }
202
203         memcpy(m_pRealData, pdblOldReal, iMinSize * sizeof(double));
204
205         if (pdblOldImg)
206         {
207             delete[] pdblOldImg;
208             pdblOldImg = NULL;
209         }
210
211         delete[] pdblOldReal;
212         pdblOldReal = NULL;
213
214         return true;
215     }
216
217     return false;
218 }
219
220 bool SinglePoly::setZeros()
221 {
222     if (m_pRealData != NULL)
223     {
224         memset(m_pRealData, 0x00, m_iSize * sizeof(double));
225     }
226     else
227     {
228         return false;
229     }
230
231     if (isComplex() == true)
232     {
233         if (m_pImgData != NULL)
234         {
235             memset(m_pImgData, 0x00, m_iSize * sizeof(double));
236         }
237         else
238         {
239             return false;
240         }
241     }
242
243     return true;
244 }
245
246 bool SinglePoly::setCoef(Double* _pdblCoefR)
247 {
248     if (m_pRealData == NULL || _pdblCoefR == NULL)
249     {
250         return false;
251     }
252
253     double *pInR    = _pdblCoefR->getReal();
254     double *pInI    = _pdblCoefR->getImg();
255
256     return setCoef(pInR, pInI);
257 }
258
259 bool SinglePoly::setCoef(const double* _pdblCoefR, const double* _pdblCoefI)
260 {
261     if (_pdblCoefI != NULL && isComplex() == false)
262     {
263         setComplex(true);
264     }
265
266     if (_pdblCoefR != NULL)
267     {
268         memcpy(m_pRealData, _pdblCoefR, m_iSize * sizeof(double));
269     }
270
271     if (_pdblCoefI != NULL)
272     {
273         memcpy(m_pImgData, _pdblCoefI, m_iSize * sizeof(double));
274     }
275
276     return true;
277 }
278
279 void SinglePoly::whoAmI()
280 {
281     std::cout << "types::SinglePoly";
282 }
283
284 bool SinglePoly::evaluate(double _dblInR, double _dblInI, double *_pdblOutR, double *_pdblOutI)
285 {
286     *_pdblOutR = 0;
287     *_pdblOutI = 0;
288     if (m_iSize == 0)
289     {
290         return true;
291     }
292
293     for (int i = 0 ; i < m_iSize ; i++)
294     {
295         //real part
296         *_pdblOutR += m_pRealData[i] * std::pow(_dblInR, i);
297         //only if variable is complex
298         if (isComplex())
299         {
300             *_pdblOutR -= m_pImgData[i] * std::pow(_dblInI, i);
301             //img part
302             *_pdblOutI += m_pRealData[i] * std::pow(_dblInR, i);
303         }
304         *_pdblOutI += m_pRealData[i] * std::pow(_dblInI, i);
305     }
306
307     return true;
308 }
309
310 void SinglePoly::updateRank(void)
311 {
312     int iNewRank = getRank();
313     if (m_pImgData)
314     {
315         for (int i = getRank(); i > 0 ; i--)
316         {
317             if (std::fabs(m_pRealData[i]) == 0.0 && std::fabs(m_pImgData[i]) == 0.0)
318             {
319                 iNewRank--;
320             }
321             else
322             {
323                 break;
324             }
325         }
326     }
327     else
328     {
329         for (int i = getRank(); i > 0 ; i--)
330         {
331             if (std::fabs(m_pRealData[i]) == 0.0)
332             {
333                 iNewRank--;
334             }
335             else
336             {
337                 break;
338             }
339         }
340     }
341
342     if (iNewRank < getRank())
343     {
344         setRank(iNewRank, true);
345     }
346 }
347
348 bool SinglePoly::toString(std::wostringstream& ostr)
349 {
350     ostr << L"FIXME : implement SinglePoly::toString" << std::endl;
351     return true;
352 }
353
354 void SinglePoly::toStringRealImg(const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly, int iLineLen)
355 {
356     toStringInternal(m_pRealData, m_pImgData, _szVar, _pListWstPoly, iLineLen);
357 }
358
359 bool SinglePoly::subMatrixToString(std::wostringstream& /*ostr*/, int* /*_piDims*/, int /*_iDims*/)
360 {
361     return false;
362 }
363
364 void SinglePoly::toStringInternal(double *_pdblR, double *_pdblI, const std::wstring& _szVar, std::list<std::wstring>* _pListWstPoly, int iLineLen)
365 {
366     int k;
367     int iLen = 0;
368     int iLastFlush = 2;
369     int iParenthLen = 2;
370
371     std::wstring strExponentDigits (L"\u2070\u00B9\u00B2\u00B3\u2074\u2075\u2076\u2077\u2078\u2079");
372     std::vector<int> iExponentsDigits = {0};
373     std::wostringstream ostemp;
374     bool bFirst = true;
375
376 //    ostemp << L" ";
377
378     for (int i = 0 ; i < m_iSize ; i++)
379     {
380         double dblR = _pdblR[i];
381         double dblI = _pdblI == NULL ? 0 : _pdblI[i];    
382         
383         if (dblR != 0 && dblI == 0)
384         {
385             DoubleFormat df;
386             getDoubleFormat(dblR, &df);
387
388             if (iLen + df.iWidth + df.iSignLen >= iLineLen - 1)
389             {
390                 iLastFlush = i;
391                 _pListWstPoly->push_back(ostemp.str());
392                 ostemp.str(L""); //reset stream
393                 addSpaces(&ostemp, 1); //take from scilab ... why not ...
394             }
395
396             // In scientific notation case bExp == true, so we have to print point (2.000D+10s)
397             // In other case don't print point (2s)
398             df.bPrintPoint = df.bExp;
399             df.bPrintPlusSign = ! bFirst;
400             df.bPaddSign = ! bFirst;
401             df.bPrintBlank = false;
402             df.bPrintOne = i == 0;
403             addDoubleValue(&ostemp, dblR, &df);
404         }
405         else if (dblR != 0 || dblI != 0)
406         {
407             DoubleFormat dfR, dfI;
408             getDoubleFormat(dblR, &dfR);
409             getDoubleFormat(dblI, &dfI);
410             dfR.bPrintPoint = dfR.bExp;
411             dfR.bPrintBlank = false;
412             dfR.bPrintPlusSign = false;
413             dfR.bPaddSign = false;             
414             dfI.bPrintPoint = dfI.bExp;
415             dfI.bPrintBlank = false;
416             dfI.bPaddSign = true;             
417             dfI.bPrintOne = false;
418             if (dblR != 0)
419              {
420                  dfR.bPaddSign = false;
421                  dfI.bPrintPlusSign = true;
422                  iLen += (i!= 0 ? iParenthLen : 0);
423              }
424              else
425              {
426                  dfI.bPrintPlusSign = ! bFirst;
427                  dfI.bPaddSign = ! bFirst;
428              }
429
430              if (iLen + dfR.iWidth + dfR.iSignLen + dfI.iWidth + dfI.iSignLen + _szVar.length() + iExponentsDigits.size() >= iLineLen - 1)
431              {
432                  iLastFlush = i;
433                  _pListWstPoly->push_back(ostemp.str());
434                  ostemp.str(L""); //reset stream
435                  addSpaces(&ostemp, 1); //take from scilab ... why not ...
436              }
437
438              if (dblR != 0)
439              {
440                  if (bFirst == false)
441                  {
442                      if (dblR > 0)
443                      {
444                          ostemp << L"+";     
445                      }
446                      else
447                      {
448                          dblR = -dblR;
449                          dblI = -dblI;
450                          ostemp << L"-"; 
451                      }   
452                  }
453                  if (i != 0)
454                  {
455                      ostemp << L"(";
456                  }
457                  addDoubleValue(&ostemp, dblR, &dfR);
458              }
459              addDoubleValue(&ostemp, dblI, &dfI);
460              ostemp << L"i";
461              
462              if (dblR != 0 & i != 0)
463              {
464                  ostemp << L")";
465              }
466         }
467         
468         if (dblR != 0 || dblI != 0)
469         {            
470             bFirst = false;
471             if (i == 1)
472             {
473                 // add polynomial variable
474                 ostemp << _szVar;
475             }
476             else if (i != 0)
477             {
478                 // add polynomial variable and exponent
479                 ostemp << _szVar;
480                 for (auto it = iExponentsDigits.rbegin(); it != iExponentsDigits.rend(); ++it)
481                 {
482                     ostemp << strExponentDigits[*it];
483                 }
484             }
485             if (i < m_iSize-1)
486             {
487                 ostemp << L" ";
488             }
489             iLen = static_cast<int>(ostemp.str().size());
490         }
491
492         for (k=0; k < iExponentsDigits.size() && iExponentsDigits[k] == 9; k++)
493         {
494             iExponentsDigits[k] = 0;
495         }
496         if (k == iExponentsDigits.size())
497         {
498             iExponentsDigits.push_back(0);
499         }
500         iExponentsDigits[k]++;
501     }
502
503     if (iLastFlush != 0)
504     {
505         if (ostemp.str() == L"")
506         {
507             ostemp << L"0";
508         }
509
510         _pListWstPoly->push_back(ostemp.str());
511     }
512
513     return;
514 }
515
516 bool SinglePoly::operator==(const InternalType& it)
517 {
518     if (const_cast<InternalType &>(it).isSinglePoly() == false)
519     {
520         return false;
521     }
522
523     SinglePoly* pP = const_cast<InternalType &>(it).getAs<SinglePoly>();
524
525     if (getRank() != pP->getRank())
526     {
527         return false;
528     }
529
530     double *pdblReal = pP->get();
531     for (int i = 0 ; i < getSize() ; i++)
532     {
533         if (m_pRealData[i] != pdblReal[i])
534         {
535             return false;
536         }
537     }
538
539     //both complex
540     if (isComplex() && pP->isComplex())
541     {
542         double *pdblImg = pP->getImg();
543         for (int i = 0 ; i < m_iSize ; i++)
544         {
545             if (m_pImgData[i] != pdblImg[i])
546             {
547                 return false;
548             }
549         }
550     }
551     //pdbl complex check all img values == 0
552     else if (pP->isComplex())
553     {
554         double *pdblImg = pP->getImg();
555         for (int i = 0 ; i < m_iSize ; i++)
556         {
557             if (pdblImg[i])
558             {
559                 return false;
560             }
561         }
562     }
563     //complex check all img values == 0
564     else if (isComplex())
565     {
566         for (int i = 0 ; i < m_iSize ; i++)
567         {
568             if (m_pImgData[i])
569             {
570                 return false;
571             }
572         }
573     }
574
575     return true;
576 }
577
578 bool SinglePoly::operator!=(const InternalType& it)
579 {
580     return !(*this == it);
581 }
582
583 SinglePoly* SinglePoly::clone()
584 {
585     SinglePoly* pPoly = NULL;
586     double *pR = NULL;
587     if (isComplex())
588     {
589         double *pI = NULL;
590         pPoly = new SinglePoly(&pR, &pI, getRank());
591         pPoly->setCoef(m_pRealData, m_pImgData);
592     }
593     else
594     {
595         pPoly = new SinglePoly(&pR, getRank());
596         pPoly->setCoef(m_pRealData, NULL);
597     }
598     return pPoly;
599 }
600
601 SinglePoly* SinglePoly::conjugate()
602 {
603     if (isComplex())
604     {
605         double *pR = NULL;
606         double *pI = NULL;
607         SinglePoly * pPoly = new SinglePoly(&pR, &pI, getRank());
608
609         Transposition::conjugate(m_iSize, m_pRealData, pR, m_pImgData, pI);
610
611         return pPoly;
612     }
613     else
614     {
615         return clone();
616     }
617 }
618
619 SinglePoly* operator*(const SinglePoly& _lhs, const SinglePoly& _rhs)
620 {
621     SinglePoly& lhs = const_cast<SinglePoly &>(_lhs);
622     SinglePoly& rhs = const_cast<SinglePoly &>(_rhs);
623     SinglePoly* pOut = NULL;
624
625     bool isComplexL = lhs.isComplex();
626     bool isComplexR = rhs.isComplex();
627     bool isComplexOut = isComplexL || isComplexR;
628
629     int iRankL = lhs.getRank();
630     int iRankR = rhs.getRank();
631     int iRankOut = lhs.getRank() + rhs.getRank();
632
633     double* pdblOutR = NULL;
634     double* pdblOutI = NULL;
635     double* pdblLR = lhs.get();
636     double* pdblLI = lhs.getImg();
637     double* pdblRR = rhs.get();
638     double* pdblRI = rhs.getImg();
639
640     if (isComplexOut)
641     {
642         pOut = new SinglePoly(&pdblOutR, &pdblOutI, iRankOut);
643         memset(pdblOutR, 0x00, sizeof(double) * (iRankOut + 1));
644         memset(pdblOutI, 0x00, sizeof(double) * (iRankOut + 1));
645     }
646     else
647     {
648         pOut = new SinglePoly(&pdblOutR, iRankOut);
649         memset(pdblOutR, 0x00, sizeof(double) * (iRankOut + 1));
650     }
651
652     if (isComplexL)
653     {
654         if (isComplexR)
655         {
656             for (int i = 0 ; i < iRankL + 1; ++i)
657             {
658                 for (int j = 0 ; j < iRankR + 1; ++j)
659                 {
660                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j] - pdblLI[i] * pdblRI[j];
661                     pdblOutI[i + j]  += pdblLI[i] * pdblRR[j] + pdblLR[i] * pdblRI[j];
662                 }
663             }
664         }
665         else
666         {
667             for (int i = 0 ; i < iRankL + 1 ; ++i)
668             {
669                 for (int j = 0 ; j < iRankR + 1 ; ++j)
670                 {
671                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
672                     pdblOutI[i + j]  += pdblLI[i] * pdblRR[j];
673                 }
674             }
675         }
676     }
677     else
678     {
679         if (isComplexR)
680         {
681             for (int i = 0 ; i < iRankL + 1 ; ++i)
682             {
683                 for (int j = 0 ; j < iRankR + 1 ; ++j)
684                 {
685                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
686                     pdblOutI[i + j]  += pdblLR[i] * pdblRI[j];
687                 }
688             }
689         }
690         else
691         {
692             for (int i = 0 ; i < iRankL + 1 ; ++i)
693             {
694                 for (int j = 0 ; j < iRankR + 1 ; ++j)
695                 {
696                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
697                 }
698             }
699         }
700     }
701
702     return pOut;
703 }
704 }
705
706
707