fix Windows warning about string functions and merge os_xxxx.h in one file
[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             os_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         os_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     return true;
332 }
333
334 void SinglePoly::toStringReal(wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
335 {
336     toStringInternal(m_pRealData, _szVar, _pListExp, _pListCoef);
337 }
338
339 void SinglePoly::toStringImg(wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
340 {
341     if (isComplex() == false)
342     {
343         _pListExp->clear();
344         _pListCoef->clear();
345         return;
346     }
347
348     toStringInternal(m_pImgData, _szVar, _pListExp, _pListCoef);
349 }
350
351 bool SinglePoly::subMatrixToString(wostringstream& /*ostr*/, int* /*_piDims*/, int /*_iDims*/)
352 {
353     return false;
354 }
355
356 void SinglePoly::toStringInternal(double *_pdblVal, wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
357 {
358     int iLineLen = ConfigVariable::getConsoleWidth();
359
360     wostringstream ostemp;
361     wostringstream ostemp2;
362
363     ostemp << L" ";
364     ostemp2 << L" ";
365
366     int iLen = 0;
367     int iLastFlush = 2;
368     for (int i = 0 ; i < m_iSize ; i++)
369     {
370         if (isRealZero(_pdblVal[i]) == false)
371         {
372             DoubleFormat df;
373             getDoubleFormat(_pdblVal[i], &df);
374
375             if (iLen + df.iWidth + df.iSignLen >= iLineLen - 1)
376             {
377                 iLastFlush = i;
378                 _pListExp->push_back(ostemp2.str());
379                 ostemp2.str(L""); //reset stream
380                 addSpaces(&ostemp2, 11); //take from scilab ... why not ...
381
382                 _pListCoef->push_back(ostemp.str());
383                 ostemp.str(L""); //reset stream
384                 addSpaces(&ostemp, 11); //take from scilab ... why not ...
385             }
386
387             bool bFirst = ostemp.str().size() == 1;
388
389             // In scientific notation case bExp == true, so we have to print point (2.000D+10s)
390             // In other case don't print point (2s)
391             df.bPrintPoint = df.bExp;
392             df.bPrintPlusSign = bFirst == false;
393             df.bPrintOne = i == 0;
394             addDoubleValue(&ostemp, _pdblVal[i], &df);
395
396             if (i == 0)
397             {
398                 iLen = static_cast<int>(ostemp.str().size());
399             }
400             else if (i == 1)
401             {
402                 // add polynom name
403                 ostemp << _szVar;
404                 iLen = static_cast<int>(ostemp.str().size());
405             }
406             else
407             {
408                 // add polynom name and exponent
409                 ostemp << _szVar;
410                 iLen = static_cast<int>(ostemp.str().size());
411                 addSpaces(&ostemp2, iLen - static_cast<int>(ostemp2.str().size()));
412                 ostemp2 << i;
413                 int iSize = static_cast<int>(ostemp2.str().size()) - iLen;
414                 addSpaces(&ostemp, iSize);
415             }
416         }
417     }
418
419     if (iLastFlush != 0)
420     {
421         if (ostemp.str() == L" ")
422         {
423             ostemp << L"  0";
424             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
425         }
426
427         if (ostemp2.str() == L" ")
428         {
429             // -1 because ostemp2 have already a space
430             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()) - 1);
431         }
432
433         _pListExp->push_back(ostemp2.str());
434         _pListCoef->push_back(ostemp.str());
435     }
436
437     return;
438 }
439
440 bool SinglePoly::operator==(const InternalType& it)
441 {
442     if (const_cast<InternalType &>(it).isSinglePoly() == false)
443     {
444         return false;
445     }
446
447     SinglePoly* pP = const_cast<InternalType &>(it).getAs<SinglePoly>();
448
449     if (getRank() != pP->getRank())
450     {
451         return false;
452     }
453
454     double *pdblReal = pP->get();
455     for (int i = 0 ; i < getSize() ; i++)
456     {
457         if (m_pRealData[i] != pdblReal[i])
458         {
459             return false;
460         }
461     }
462
463     //both complex
464     if (isComplex() && pP->isComplex())
465     {
466         double *pdblImg = pP->getImg();
467         for (int i = 0 ; i < m_iSize ; i++)
468         {
469             if (m_pImgData[i] != pdblImg[i])
470             {
471                 return false;
472             }
473         }
474     }
475     //pdbl complex check all img values == 0
476     else if (pP->isComplex())
477     {
478         double *pdblImg = pP->getImg();
479         for (int i = 0 ; i < m_iSize ; i++)
480         {
481             if (pdblImg[i])
482             {
483                 return false;
484             }
485         }
486     }
487     //complex check all img values == 0
488     else if (isComplex())
489     {
490         for (int i = 0 ; i < m_iSize ; i++)
491         {
492             if (m_pImgData[i])
493             {
494                 return false;
495             }
496         }
497     }
498
499     return true;
500 }
501
502 bool SinglePoly::operator!=(const InternalType& it)
503 {
504     return !(*this == it);
505 }
506
507 SinglePoly* SinglePoly::clone()
508 {
509     SinglePoly* pPoly = NULL;
510     double *pR = NULL;
511     if (isComplex())
512     {
513         double *pI = NULL;
514         pPoly = new SinglePoly(&pR, &pI, getRank());
515         pPoly->setCoef(m_pRealData, m_pImgData);
516     }
517     else
518     {
519         pPoly = new SinglePoly(&pR, getRank());
520         pPoly->setCoef(m_pRealData, NULL);
521     }
522     return pPoly;
523 }
524
525 SinglePoly* SinglePoly::conjugate()
526 {
527     if (isComplex())
528     {
529         double *pR = NULL;
530         double *pI = NULL;
531         SinglePoly * pPoly = new SinglePoly(&pR, &pI, getRank());
532
533         Transposition::conjugate(m_iSize, m_pRealData, pR, m_pImgData, pI);
534
535         return pPoly;
536     }
537     else
538     {
539         return clone();
540     }
541 }
542
543 SinglePoly* operator*(const SinglePoly& _lhs, const SinglePoly& _rhs)
544 {
545     SinglePoly& lhs = const_cast<SinglePoly &>(_lhs);
546     SinglePoly& rhs = const_cast<SinglePoly &>(_rhs);
547     SinglePoly* pOut = NULL;
548
549     bool isComplexL = lhs.isComplex();
550     bool isComplexR = rhs.isComplex();
551     bool isComplexOut = isComplexL || isComplexR;
552
553     int iRankL = lhs.getRank();
554     int iRankR = rhs.getRank();
555     int iRankOut = lhs.getRank() + rhs.getRank();
556
557     double* pdblOutR = NULL;
558     double* pdblOutI = NULL;
559     double* pdblLR = lhs.get();
560     double* pdblLI = lhs.getImg();
561     double* pdblRR = rhs.get();
562     double* pdblRI = rhs.getImg();
563
564     if (isComplexOut)
565     {
566         pOut = new SinglePoly(&pdblOutR, &pdblOutI, iRankOut);
567         memset(pdblOutR, 0x00, sizeof(double) * (iRankOut + 1));
568         memset(pdblOutI, 0x00, sizeof(double) * (iRankOut + 1));
569     }
570     else
571     {
572         pOut = new SinglePoly(&pdblOutR, iRankOut);
573         memset(pdblOutR, 0x00, sizeof(double) * (iRankOut + 1));
574     }
575
576     if (isComplexL)
577     {
578         if (isComplexR)
579         {
580             for (int i = 0 ; i < iRankL + 1; ++i)
581             {
582                 for (int j = 0 ; j < iRankR + 1; ++j)
583                 {
584                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j] - pdblLI[i] * pdblRI[j];
585                     pdblOutI[i + j]  += pdblLI[i] * pdblRR[j] + pdblLR[i] * pdblRI[j];
586                 }
587             }
588         }
589         else
590         {
591             for (int i = 0 ; i < iRankL + 1 ; ++i)
592             {
593                 for (int j = 0 ; j < iRankR + 1 ; ++j)
594                 {
595                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
596                     pdblOutI[i + j]  += pdblLI[i] * pdblRR[j];
597                 }
598             }
599         }
600     }
601     else
602     {
603         if (isComplexR)
604         {
605             for (int i = 0 ; i < iRankL + 1 ; ++i)
606             {
607                 for (int j = 0 ; j < iRankR + 1 ; ++j)
608                 {
609                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
610                     pdblOutI[i + j]  += pdblLR[i] * pdblRI[j];
611                 }
612             }
613         }
614         else
615         {
616             for (int i = 0 ; i < iRankL + 1 ; ++i)
617             {
618                 for (int j = 0 ; j < iRankR + 1 ; ++j)
619                 {
620                     pdblOutR[i + j]  += pdblLR[i] * pdblRR[j];
621                 }
622             }
623         }
624     }
625
626     return pOut;
627 }
628 }
629
630
631