ast: use a human-readable memory number on allocation error
[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 }
29
30 namespace types
31 {
32 SinglePoly::SinglePoly()
33 {
34     double* pdblCoefR = NULL;
35     int piDims[2] = {1, 1};
36     create(piDims, 2, &pdblCoefR, NULL);
37     pdblCoefR[0] = 0;
38 #ifndef NDEBUG
39     Inspector::addItem(this);
40 #endif
41 }
42
43 SinglePoly::SinglePoly(double** _pdblCoefR, int _iRank)
44 {
45     int piDims[2] = {_iRank + 1, 1};
46     create(piDims, 2, _pdblCoefR, NULL);
47 #ifndef NDEBUG
48     Inspector::addItem(this);
49 #endif
50 }
51
52 SinglePoly::SinglePoly(double** _pdblCoefR, double** _pdblCoefI, int _iRank)
53 {
54     int piDims[2] = {_iRank + 1, 1};
55     create(piDims, 2, _pdblCoefR, _pdblCoefI);
56 #ifndef NDEBUG
57     Inspector::addItem(this);
58 #endif
59 }
60
61 SinglePoly::~SinglePoly()
62 {
63     deleteAll();
64 #ifndef NDEBUG
65     Inspector::removeItem(this);
66 #endif
67 }
68
69 void SinglePoly::deleteAll()
70 {
71     delete[] m_pRealData;
72     m_pRealData = NULL;
73     deleteImg();
74 }
75
76 void SinglePoly::deleteImg()
77 {
78     if (m_pImgData != NULL)
79     {
80         delete[] m_pImgData;
81         m_pImgData = NULL;
82     }
83 }
84
85 double SinglePoly::getNullValue()
86 {
87     return 0;
88 }
89
90 SinglePoly* SinglePoly::createEmpty(int /*_iDims*/, int* _piDims, bool _bComplex)
91 {
92     double* pdblData = NULL;
93     SinglePoly* pSP = new SinglePoly(&pdblData, _piDims[0] - 1);
94     pSP->setComplex(_bComplex);
95
96     return pSP;
97 }
98
99 double* SinglePoly::allocData(int _iSize)
100 {
101     double* pDbl = NULL;
102     try
103     {
104         if (_iSize < 0)
105         {
106             m_pRealData = NULL;
107             m_pImgData = NULL;
108             char message[bsiz];
109             os_sprintf(message, _("Can not allocate negative size (%d).\n"),  _iSize);
110             throw ast::InternalError(message);
111         }
112         else
113         {
114             pDbl = new double[_iSize];
115         }
116     }
117     catch (std::bad_alloc &/*e*/)
118     {
119         char message[bsiz];
120         char byteString[9];
121         humanReadableByteCount(((size_t) m_iSize) * sizeof(double), byteString);
122         os_sprintf(message, _("Can not allocate %s memory.\n"), byteString);
123         throw ast::InternalError(message);
124     }
125
126     return pDbl;
127 }
128
129 double SinglePoly::copyValue(double _dblData)
130 {
131     return _dblData;
132 }
133
134 int SinglePoly::getRank()
135 {
136     return m_iSize - 1;
137 }
138
139 double SinglePoly::getDegree()
140 {
141     return m_iSize == 1 && m_pRealData[0] == 0 && (m_pImgData == NULL || m_pImgData[0] == 0) ? -INFINITY : m_iSize - 1;
142 }
143
144 bool SinglePoly::setRank(int _iRank, bool bSave)
145 {
146     double *pR = NULL;
147     double *pI = NULL;
148     if (bSave == false)
149     {
150         if (getRank() != _iRank)
151         {
152             int piDims[2] = {_iRank + 1, 1};
153             if (m_pImgData == NULL)
154             {
155                 deleteAll();
156                 create(piDims, 2, &pR, NULL);
157             }
158             else
159             {
160                 deleteAll();
161                 create(piDims, 2, &pR, &pI);
162             }
163
164             return true;
165         }
166
167         return true;
168     }
169     else
170     {
171         double* pdblOldReal = m_pRealData;
172         double* pdblOldImg  = m_pImgData;
173         int iMinSize = Min(m_iSize, _iRank + 1);
174         int piDims[2] = {_iRank + 1, 1};
175
176         if (m_pImgData == NULL)
177         {
178             create(piDims, 2, &pR, NULL);
179         }
180         else
181         {
182             create(piDims, 2, &pR, &pI);
183             memcpy(m_pImgData, pdblOldImg, iMinSize * sizeof(double));
184         }
185
186         memcpy(m_pRealData, pdblOldReal, iMinSize * sizeof(double));
187
188         if (pdblOldImg)
189         {
190             delete[] pdblOldImg;
191             pdblOldImg = NULL;
192         }
193
194         delete[] pdblOldReal;
195         pdblOldReal = NULL;
196
197         return true;
198     }
199
200     return false;
201 }
202
203 bool SinglePoly::setZeros()
204 {
205     if (m_pRealData != NULL)
206     {
207         memset(m_pRealData, 0x00, m_iSize * sizeof(double));
208     }
209     else
210     {
211         return false;
212     }
213
214     if (isComplex() == true)
215     {
216         if (m_pImgData != NULL)
217         {
218             memset(m_pImgData, 0x00, m_iSize * sizeof(double));
219         }
220         else
221         {
222             return false;
223         }
224     }
225
226     return true;
227 }
228
229 bool SinglePoly::setCoef(Double* _pdblCoefR)
230 {
231     if (m_pRealData == NULL || _pdblCoefR == NULL)
232     {
233         return false;
234     }
235
236     double *pInR    = _pdblCoefR->getReal();
237     double *pInI    = _pdblCoefR->getImg();
238
239     return setCoef(pInR, pInI);
240 }
241
242 bool SinglePoly::setCoef(const double* _pdblCoefR, const double* _pdblCoefI)
243 {
244     if (_pdblCoefI != NULL && isComplex() == false)
245     {
246         setComplex(true);
247     }
248
249     if (_pdblCoefR != NULL)
250     {
251         memcpy(m_pRealData, _pdblCoefR, m_iSize * sizeof(double));
252     }
253
254     if (_pdblCoefI != NULL)
255     {
256         memcpy(m_pImgData, _pdblCoefI, m_iSize * sizeof(double));
257     }
258
259     return true;
260 }
261
262 void SinglePoly::whoAmI()
263 {
264     std::cout << "types::SinglePoly";
265 }
266
267 bool SinglePoly::evaluate(double _dblInR, double _dblInI, double *_pdblOutR, double *_pdblOutI)
268 {
269     *_pdblOutR = 0;
270     *_pdblOutI = 0;
271     if (m_iSize == 0)
272     {
273         return true;
274     }
275
276     for (int i = 0 ; i < m_iSize ; i++)
277     {
278         //real part
279         *_pdblOutR += m_pRealData[i] * std::pow(_dblInR, i);
280         //only if variable is complex
281         if (isComplex())
282         {
283             *_pdblOutR -= m_pImgData[i] * std::pow(_dblInI, i);
284             //img part
285             *_pdblOutI += m_pRealData[i] * std::pow(_dblInR, i);
286         }
287         *_pdblOutI += m_pRealData[i] * std::pow(_dblInI, i);
288     }
289
290     return true;
291 }
292
293 void SinglePoly::updateRank(void)
294 {
295     int iNewRank = getRank();
296     if (m_pImgData)
297     {
298         for (int i = getRank(); i > 0 ; i--)
299         {
300             if (std::fabs(m_pRealData[i]) == 0.0 && std::fabs(m_pImgData[i]) == 0.0)
301             {
302                 iNewRank--;
303             }
304             else
305             {
306                 break;
307             }
308         }
309     }
310     else
311     {
312         for (int i = getRank(); i > 0 ; i--)
313         {
314             if (std::fabs(m_pRealData[i]) == 0.0)
315             {
316                 iNewRank--;
317             }
318             else
319             {
320                 break;
321             }
322         }
323     }
324
325     if (iNewRank < getRank())
326     {
327         setRank(iNewRank, true);
328     }
329 }
330
331 bool SinglePoly::toString(std::wostringstream& ostr)
332 {
333     ostr << L"FIXME : implement SinglePoly::toString" << std::endl;
334     return true;
335 }
336
337 void SinglePoly::toStringReal(const std::wstring& _szVar, std::list<std::wstring>* _pListExp, std::list<std::wstring>* _pListCoef)
338 {
339     toStringInternal(m_pRealData, _szVar, _pListExp, _pListCoef);
340 }
341
342 void SinglePoly::toStringImg(const std::wstring& _szVar, std::list<std::wstring>* _pListExp, std::list<std::wstring>* _pListCoef)
343 {
344     if (isComplex() == false)
345     {
346         _pListExp->clear();
347         _pListCoef->clear();
348         return;
349     }
350
351     toStringInternal(m_pImgData, _szVar, _pListExp, _pListCoef);
352 }
353
354 bool SinglePoly::subMatrixToString(std::wostringstream& /*ostr*/, int* /*_piDims*/, int /*_iDims*/)
355 {
356     return false;
357 }
358
359 void SinglePoly::toStringInternal(double *_pdblVal, const std::wstring& _szVar, std::list<std::wstring>* _pListExp, std::list<std::wstring>* _pListCoef)
360 {
361     int iLineLen = ConfigVariable::getConsoleWidth();
362
363     std::wostringstream ostemp;
364     std::wostringstream ostemp2;
365
366     ostemp << L" ";
367     ostemp2 << L" ";
368
369     int iLen = 0;
370     int iLastFlush = 2;
371     for (int i = 0 ; i < m_iSize ; i++)
372     {
373         if (_pdblVal[i] != 0)
374         {
375             DoubleFormat df;
376             getDoubleFormat(_pdblVal[i], &df);
377
378             if (iLen + df.iWidth + df.iSignLen >= iLineLen - 1)
379             {
380                 iLastFlush = i;
381                 _pListExp->push_back(ostemp2.str());
382                 ostemp2.str(L""); //reset stream
383                 addSpaces(&ostemp2, 11); //take from scilab ... why not ...
384
385                 _pListCoef->push_back(ostemp.str());
386                 ostemp.str(L""); //reset stream
387                 addSpaces(&ostemp, 11); //take from scilab ... why not ...
388             }
389
390             bool bFirst = ostemp.str().size() == 1;
391
392             // In scientific notation case bExp == true, so we have to print point (2.000D+10s)
393             // In other case don't print point (2s)
394             df.bPrintPoint = df.bExp;
395             df.bPrintPlusSign = bFirst == false;
396             df.bPrintOne = i == 0;
397             addDoubleValue(&ostemp, _pdblVal[i], &df);
398
399             if (i == 0)
400             {
401                 iLen = static_cast<int>(ostemp.str().size());
402             }
403             else if (i == 1)
404             {
405                 // add polynom name
406                 ostemp << _szVar;
407                 iLen = static_cast<int>(ostemp.str().size());
408             }
409             else
410             {
411                 // add polynom name and exponent
412                 ostemp << _szVar;
413                 iLen = static_cast<int>(ostemp.str().size());
414                 addSpaces(&ostemp2, iLen - static_cast<int>(ostemp2.str().size()));
415                 ostemp2 << i;
416                 int iSize = static_cast<int>(ostemp2.str().size()) - iLen;
417                 addSpaces(&ostemp, iSize);
418             }
419         }
420     }
421
422     if (iLastFlush != 0)
423     {
424         if (ostemp.str() == L" ")
425         {
426             ostemp << L"  0";
427             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
428         }
429
430         if (ostemp2.str() == L" ")
431         {
432             // -1 because ostemp2 have already a space
433             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()) - 1);
434         }
435
436         _pListExp->push_back(ostemp2.str());
437         _pListCoef->push_back(ostemp.str());
438     }
439
440     return;
441 }
442
443 bool SinglePoly::operator==(const InternalType& it)
444 {
445     if (const_cast<InternalType &>(it).isSinglePoly() == false)
446     {
447         return false;
448     }
449
450     SinglePoly* pP = const_cast<InternalType &>(it).getAs<SinglePoly>();
451
452     if (getRank() != pP->getRank())
453     {
454         return false;
455     }
456
457     double *pdblReal = pP->get();
458     for (int i = 0 ; i < getSize() ; i++)
459     {
460         if (m_pRealData[i] != pdblReal[i])
461         {
462             return false;
463         }
464     }
465
466     //both complex
467     if (isComplex() && pP->isComplex())
468     {
469         double *pdblImg = pP->getImg();
470         for (int i = 0 ; i < m_iSize ; i++)
471         {
472             if (m_pImgData[i] != pdblImg[i])
473             {
474                 return false;
475             }
476         }
477     }
478     //pdbl complex check all img values == 0
479     else if (pP->isComplex())
480     {
481         double *pdblImg = pP->getImg();
482         for (int i = 0 ; i < m_iSize ; i++)
483         {
484             if (pdblImg[i])
485             {
486                 return false;
487             }
488         }
489     }
490     //complex check all img values == 0
491     else if (isComplex())
492     {
493         for (int i = 0 ; i < m_iSize ; i++)
494         {
495             if (m_pImgData[i])
496             {
497                 return false;
498             }
499         }
500     }
501
502     return true;
503 }
504
505 bool SinglePoly::operator!=(const InternalType& it)
506 {
507     return !(*this == it);
508 }
509
510 SinglePoly* SinglePoly::clone()
511 {
512     SinglePoly* pPoly = NULL;
513     double *pR = NULL;
514     if (isComplex())
515     {
516         double *pI = NULL;
517         pPoly = new SinglePoly(&pR, &pI, getRank());
518         pPoly->setCoef(m_pRealData, m_pImgData);
519     }
520     else
521     {
522         pPoly = new SinglePoly(&pR, getRank());
523         pPoly->setCoef(m_pRealData, NULL);
524     }
525     return pPoly;
526 }
527
528 SinglePoly* SinglePoly::conjugate()
529 {
530     if (isComplex())
531     {
532         double *pR = NULL;
533         double *pI = NULL;
534         SinglePoly * pPoly = new SinglePoly(&pR, &pI, getRank());
535
536         Transposition::conjugate(m_iSize, m_pRealData, pR, m_pImgData, pI);
537
538         return pPoly;
539     }
540     else
541     {
542         return clone();
543     }
544 }
545
546 SinglePoly* operator*(const SinglePoly& _lhs, const SinglePoly& _rhs)
547 {
548     SinglePoly& lhs = const_cast<SinglePoly &>(_lhs);
549     SinglePoly& rhs = const_cast<SinglePoly &>(_rhs);
550     SinglePoly* pOut = NULL;
551
552     bool isComplexL = lhs.isComplex();
553     bool isComplexR = rhs.isComplex();
554     bool isComplexOut = isComplexL || isComplexR;
555
556     int iRankL = lhs.getRank();
557     int iRankR = rhs.getRank();
558     int iRankOut = lhs.getRank() + rhs.getRank();
559
560     double* pdblOutR = NULL;
561     double* pdblOutI = NULL;
562     double* pdblLR = lhs.get();
563     double* pdblLI = lhs.getImg();
564     double* pdblRR = rhs.get();
565     double* pdblRI = rhs.getImg();
566
567     if (isComplexOut)
568     {
569         pOut = new SinglePoly(&pdblOutR, &pdblOutI, iRankOut);
570         memset(pdblOutR, 0x00, sizeof(double) * (iRankOut + 1));
571         memset(pdblOutI, 0x00, sizeof(double) * (iRankOut + 1));
572     }
573     else
574     {
575         pOut = new SinglePoly(&pdblOutR, iRankOut);
576         memset(pdblOutR, 0x00, sizeof(double) * (iRankOut + 1));
577     }
578
579     if (isComplexL)
580     {
581         if (isComplexR)
582         {
583             for (int i = 0 ; i < iRankL + 1; ++i)
584             {
585                 for (int j = 0 ; j < iRankR + 1; ++j)
586                 {
587                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j] - pdblLI[i] * pdblRI[j];
588                     pdblOutI[i + j]  += pdblLI[i] * pdblRR[j] + pdblLR[i] * pdblRI[j];
589                 }
590             }
591         }
592         else
593         {
594             for (int i = 0 ; i < iRankL + 1 ; ++i)
595             {
596                 for (int j = 0 ; j < iRankR + 1 ; ++j)
597                 {
598                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
599                     pdblOutI[i + j]  += pdblLI[i] * pdblRR[j];
600                 }
601             }
602         }
603     }
604     else
605     {
606         if (isComplexR)
607         {
608             for (int i = 0 ; i < iRankL + 1 ; ++i)
609             {
610                 for (int j = 0 ; j < iRankR + 1 ; ++j)
611                 {
612                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
613                     pdblOutI[i + j]  += pdblLR[i] * pdblRI[j];
614                 }
615             }
616         }
617         else
618         {
619             for (int i = 0 ; i < iRankL + 1 ; ++i)
620             {
621                 for (int j = 0 ; j < iRankR + 1 ; ++j)
622                 {
623                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
624                 }
625             }
626         }
627     }
628
629     return pOut;
630 }
631 }
632
633
634