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