0a85403dc5ff0880f1c55247cf5e1748688e0842
[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
19 extern "C"
20 {
21 #include "log.h"
22 #include "exp.h"
23 #include "elem_common.h"
24 }
25
26 using namespace std;
27
28 namespace types
29 {
30 SinglePoly::SinglePoly()
31 {
32     int iRank = 1;
33     double* pdblCoefR = NULL;
34     createPoly(&pdblCoefR, NULL, iRank);
35     pdblCoefR[0] = 0;
36 }
37
38 SinglePoly::SinglePoly(double** _pdblCoefR, int _iRank)
39 {
40     createPoly(_pdblCoefR, NULL, _iRank);
41 }
42
43 SinglePoly::SinglePoly(double** _pdblCoefR, double** _pdblCoefI, int _iRank)
44 {
45     createPoly(_pdblCoefR, _pdblCoefI, _iRank);
46 }
47
48 SinglePoly::SinglePoly(Double** _poCoefR, int _iRank)
49 {
50     double *pR  = NULL;
51     double *pI  = NULL;
52     createPoly(&pR, &pI, _iRank);
53     *_poCoefR = m_pdblCoef;
54 }
55
56
57 SinglePoly::~SinglePoly()
58 {
59     if (m_pdblCoef)
60     {
61         delete m_pdblCoef;
62     }
63 }
64
65 /*Real constructor, private only*/
66 void SinglePoly::createPoly(double** _pdblCoefR, double** _pdblCoefI, int _iRank)
67 {
68     double *pR  = NULL;
69     double *pI  = NULL;
70     m_bComplex  = false;
71     m_iRank     = _iRank;
72
73     if (m_iRank == 0)
74     {
75         m_pdblCoef = NULL;
76         return;
77     }
78
79     if (_pdblCoefI != NULL)
80     {
81         m_pdblCoef = new Double(1, _iRank, &pR, &pI);
82     }
83     else
84     {
85         m_pdblCoef = new Double(1, _iRank, &pR);
86     }
87
88     m_pdblCoef->IncreaseRef();
89     m_pdblCoef->setZeros();
90     if (_pdblCoefR != NULL)
91     {
92         *_pdblCoefR = pR;
93     }
94
95     if (_pdblCoefI != NULL)
96     {
97         m_bComplex = true;
98         *_pdblCoefI = pI;
99     }
100 }
101
102 int SinglePoly::getRank()
103 {
104     return m_iRank;
105 }
106
107 int SinglePoly::getRealRank()
108 {
109     return m_iRank - 1;
110 }
111
112 bool SinglePoly::setRank(int _iRank, bool bSave)
113 {
114     double *pR  = NULL;
115     double *pI  = NULL;
116     if (bSave == false)
117     {
118         if (m_iRank != _iRank)
119         {
120             delete m_pdblCoef;
121
122             if (m_bComplex == false)
123             {
124                 createPoly(&pR, NULL, _iRank);
125             }
126             else
127             {
128                 createPoly(&pR, &pI, _iRank);
129             }
130             return true;
131         }
132         return true;
133     }
134     else
135     {
136         Double *pCoef = NULL;
137         if (_iRank != 0)
138         {
139             pCoef = new Double(1, _iRank, &pR, &pI);
140             pCoef->set(m_pdblCoef->getReal());
141             pCoef->setComplex(m_pdblCoef->isComplex());
142             if (m_pdblCoef->isComplex())
143             {
144                 pCoef->setImg(m_pdblCoef->getImg());
145             }
146             m_iRank = _iRank;
147         }
148         else
149         {
150             m_iRank = 1;
151             pCoef = new Double(1, 1, &pR, &pI);
152             pCoef->setComplex(m_pdblCoef->isComplex());
153             pCoef->set(0, 0, 0);
154         }
155
156         m_pdblCoef->DecreaseRef();
157         if (m_pdblCoef->isDeletable())
158         {
159             delete m_pdblCoef;
160         }
161
162         m_pdblCoef = pCoef;
163         m_pdblCoef->IncreaseRef();
164         return true;
165     }
166     return false;
167 }
168
169 Double* SinglePoly::getCoef()
170 {
171     return m_pdblCoef;
172 }
173
174 double* SinglePoly::getCoefReal()
175 {
176     return m_pdblCoef->getReal();
177 }
178
179 double* SinglePoly::getCoefImg()
180 {
181     return m_pdblCoef->getImg();
182 }
183
184 bool SinglePoly::setCoef(Double* _pdblCoefR)
185 {
186     if (m_pdblCoef == NULL || _pdblCoefR == NULL)
187     {
188         return false;
189     }
190
191     double *pInR        = _pdblCoefR->getReal();
192     double *pInI        = _pdblCoefR->getImg();
193
194     return setCoef(pInR, pInI);
195 }
196
197 void SinglePoly::setComplex(bool _bComplex)
198 {
199     m_pdblCoef->setComplex(_bComplex);
200     m_bComplex = _bComplex;
201 }
202
203 bool SinglePoly::setCoef(double* _pdblCoefR, double* _pdblCoefI)
204 {
205     if (m_pdblCoef == NULL)
206     {
207         return false;
208     }
209
210     if (_pdblCoefI != NULL && isComplex() == false)
211     {
212         m_pdblCoef->setComplex(true);
213         m_bComplex = true;
214     }
215
216     double *pR = m_pdblCoef->getReal();
217     double *pI = m_pdblCoef->getImg();
218
219     if (_pdblCoefR != NULL && pR != NULL)
220     {
221         memcpy(pR, _pdblCoefR, m_iRank * sizeof(double));
222     }
223
224     if (_pdblCoefI != NULL && pI != NULL)
225     {
226         memcpy(pI, _pdblCoefI, m_iRank * sizeof(double));
227     }
228
229     return true;
230 }
231
232 void SinglePoly::whoAmI()
233 {
234     std::cout << "types::SinglePoly";
235 }
236
237 bool SinglePoly::isComplex()
238 {
239     return m_bComplex;
240 }
241
242 GenericType* SinglePoly::getColumnValues(int _iPos)
243 {
244     return NULL;
245 }
246
247 bool SinglePoly::evaluate(double _dblInR, double _dblInI, double *_pdblOutR, double *_pdblOutI)
248 {
249     double *pCoefR = m_pdblCoef->getReal();
250     double *pCoefI = m_pdblCoef->getImg();
251
252     *_pdblOutR = 0;
253     *_pdblOutI = 0;
254     if (m_iRank == 0)
255     {
256         return true;
257     }
258
259     for (int i = 0 ; i < m_iRank ; i++)
260     {
261         //real part
262         *_pdblOutR += pCoefR[i] * pow(_dblInR, i);
263         //only if variable is complex
264         if (m_pdblCoef->isComplex())
265         {
266             *_pdblOutR -= pCoefI[i] * pow(_dblInI, i);
267             //img part
268             *_pdblOutI += pCoefI[i] * pow(_dblInR, i);
269         }
270         *_pdblOutI += pCoefR[i] * pow(_dblInI, i);
271     }
272
273     //old version, does not work
274     //for(int i = m_iRank - 1 ; i >= 0 ; i--)
275     //{
276     //  //(a1 + ib1)(a2 + ib2)**n = (a1 + ib1) * exp(n * log(a2 + ib2))
277     //  double dblLogR = 0;
278     //  double dblLogI = 0;
279     //  double dblExpR = 0;
280     //  double dblExpI = 0;
281
282     //  //log(a2 + ib2)
283     //  if(_dblInI != 0)
284     //  {
285     //          wlog(_dblInR, _dblInI, &dblLogR, &dblLogI);
286     //  }
287     //  else
288     //  {
289     //          dblLogR = dlogs(_dblInR);
290     //  }
291
292     //  //n * log(a2 + ib2)
293     //  dblLogR *= i;
294     //  dblLogI *= i;
295
296     //  //exp(n * log(a2 + ib2))
297     //  if(dblLogI != 0)
298     //  {
299     //          zexps(dblLogR, dblLogI, &dblExpR, &dblExpI);
300     //  }
301     //  else
302     //  {
303     //          dblExpR = dexps(dblLogR);
304     //  }
305
306     //  //(a1 + ib1) * exp(n * log(a2 + ib2))
307     //  if(m_pdblCoef->isComplex())
308     //  {
309     //          *_pdblOutR += (dblExpR * pCoefR[i] - dblExpI * pCoefI[i]);
310     //          *_pdblOutI += (dblExpR * pCoefI[i] + dblExpI * pCoefR[i]);
311     //  }
312     //  else
313     //  {
314     //          *_pdblOutR += (dblExpR * pCoefR[i]);
315     //          *_pdblOutI += (dblExpI * pCoefR[i]);
316     //  }
317     //}
318     return true;
319 }
320
321 void SinglePoly::updateRank(void)
322 {
323     double dblEps = getRelativeMachinePrecision();
324     int iNewRank = m_iRank;
325     double *pCoefR = getCoef()->getReal();
326     double *pCoefI = getCoef()->getImg();
327     for (int i = m_iRank - 1; i > 0 ; i--)
328     {
329         if (fabs(pCoefR[i]) <= dblEps && (pCoefI != NULL ? fabs(pCoefI[i]) : 0) <= dblEps)
330         {
331             iNewRank--;
332         }
333         else
334         {
335             break;
336         }
337     }
338     if (iNewRank < m_iRank)
339     {
340         setRank(iNewRank, true);
341     }
342 }
343
344 bool SinglePoly::toString(std::wostringstream& ostr)
345 {
346     ostr << L"FIXME : implement SinglePoly::toString" << std::endl;
347     return true;
348 }
349
350 void SinglePoly::toStringReal(wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
351 {
352     toStringInternal(m_pdblCoef->getReal(), _szVar, _pListExp, _pListCoef);
353 }
354
355 void SinglePoly::toStringImg(wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
356 {
357     if (isComplex() == false)
358     {
359         _pListExp->clear();
360         _pListCoef->clear();
361         return;
362     }
363
364     toStringInternal(m_pdblCoef->getImg(), _szVar, _pListExp, _pListCoef);
365 }
366
367 void SinglePoly::toStringInternal(double *_pdblVal, wstring _szVar, list<wstring>* _pListExp , list<wstring>* _pListCoef)
368 {
369     int iPrecision = ConfigVariable::getFormatSize();
370     int iLineLen = ConfigVariable::getConsoleWidth();
371
372     wostringstream ostemp;
373     wostringstream ostemp2;
374
375     ostemp << L"  ";
376
377     //to add exponant value a the good place
378     int *piIndexExp = new int[m_iRank];
379
380     int iLen                            = 0;
381     int iLastFlush      = 2;
382     for (int i = 0 ; i < m_iRank ; i++)
383     {
384         piIndexExp[i] = 0;
385         if (isRealZero(_pdblVal[i]) == false)
386         {
387             DoubleFormat df;
388             getDoubleFormat(_pdblVal[i], &df);
389
390             if (iLen + df.iWidth + 2 >= iLineLen)
391             {
392                 //flush
393                 for (int j = iLastFlush ; j < i ; j++)
394                 {
395                     if (piIndexExp[j] == 0)
396                     {
397                         continue;
398                     }
399
400                     addSpaces(&ostemp2, piIndexExp[j] - static_cast<int>(ostemp2.str().size()));
401                     if (isRealZero(_pdblVal[j]) == false)
402                     {
403                         ostemp2 << j;
404                     }
405                 }
406                 iLastFlush = i;
407                 _pListExp->push_back(ostemp2.str());
408                 ostemp2.str(L""); //reset stream
409                 addSpaces(&ostemp2, 12); //take from scilab ... why not ...
410
411                 _pListCoef->push_back(ostemp.str());
412                 ostemp.str(L""); //reset stream
413                 addSpaces(&ostemp, 12); //take from scilab ... why not ...
414             }
415
416             bool bFirst = ostemp.str().size() == 2;
417
418             df.bPrintPoint = false;
419             df.bPrintPlusSign = ostemp.str().size() != 2;
420             df.bPrintOne = i == 0;
421             addDoubleValue(&ostemp, _pdblVal[i], &df);
422
423             if (i != 0)
424             {
425                 ostemp << _szVar;
426                 piIndexExp[i] = static_cast<int>(ostemp.str().size());
427             }
428             ostemp << L" ";
429             iLen = static_cast<int>(ostemp.str().size());
430         }
431     }
432
433     if (iLastFlush != 0)
434     {
435         for (int j = iLastFlush ; j < m_iRank ; j++)
436         {
437             if (piIndexExp[j] == 0)
438             {
439                 continue;
440             }
441
442             addSpaces(&ostemp2, piIndexExp[j] - static_cast<int>(ostemp2.str().size()));
443             if (isRealZero(_pdblVal[j]) == false)
444             {
445                 ostemp2 << j;
446             }
447         }
448
449         if (ostemp.str() == L"  ")
450         {
451             ostemp << L"  0";
452             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
453         }
454
455         _pListExp->push_back(ostemp2.str());
456         _pListCoef->push_back(ostemp.str());
457     }
458
459     delete[] piIndexExp;
460     return;
461 }
462
463 bool SinglePoly::operator==(const InternalType& it)
464 {
465     if (const_cast<InternalType &>(it).isSinglePoly() == false)
466     {
467         return false;
468     }
469
470     SinglePoly* pP = const_cast<InternalType &>(it).getAs<SinglePoly>();
471
472     if (getRank() != pP->getRank())
473     {
474         return false;
475     }
476
477     return *(getCoef()) == *(pP->getCoef());
478 }
479
480 bool SinglePoly::operator!=(const InternalType& it)
481 {
482     return !(*this == it);
483 }
484
485 SinglePoly* SinglePoly::clone()
486 {
487     SinglePoly* pPoly = NULL;
488     double *pR = NULL;
489     if (isComplex())
490     {
491         double *pI = NULL;
492         pPoly = new SinglePoly(&pR, &pI, getRank());
493         pPoly->setCoef(getCoefReal(), getCoefImg());
494     }
495     else
496     {
497         pPoly = new SinglePoly(&pR, getRank());
498         pPoly->setCoef(getCoefReal(), NULL);
499     }
500     return pPoly;
501 }
502
503 SinglePoly* SinglePoly::conjugate()
504 {
505     SinglePoly* pPoly = NULL;
506     if (isComplex())
507     {
508         double *pR = NULL;
509         double *pI = NULL;
510         SinglePoly * pPoly = new SinglePoly(&pR, &pI, getRank());
511
512         Transposition::conjugate(getRank(), getCoefReal(), pR, getCoefImg(), pI);
513
514         return pPoly;
515     }
516     else
517     {
518         return clone();
519     }
520 }
521 }
522
523