fix display power for imaginary part
[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     ostemp2 << L"";
377
378     //to add exponant value a the good place
379     int *piIndexExp = new int[m_iRank];
380
381     int iLen                            = 0;
382     int iLastFlush      = 2;
383     for (int i = 0 ; i < m_iRank ; i++)
384     {
385         piIndexExp[i] = 0;
386         if (isRealZero(_pdblVal[i]) == false)
387         {
388             DoubleFormat df;
389             getDoubleFormat(_pdblVal[i], &df);
390
391             if (iLen + df.iWidth + 2 >= iLineLen)
392             {
393                 //flush
394                 for (int j = iLastFlush ; j < i ; j++)
395                 {
396                     if (piIndexExp[j] == 0)
397                     {
398                         continue;
399                     }
400
401                     addSpaces(&ostemp2, piIndexExp[j] - static_cast<int>(ostemp2.str().size()));
402                     if (isRealZero(_pdblVal[j]) == false)
403                     {
404                         ostemp2 << j;
405                     }
406                 }
407                 iLastFlush = i;
408                 _pListExp->push_back(ostemp2.str());
409                 ostemp2.str(L""); //reset stream
410                 addSpaces(&ostemp2, 12); //take from scilab ... why not ...
411
412                 _pListCoef->push_back(ostemp.str());
413                 ostemp.str(L""); //reset stream
414                 addSpaces(&ostemp, 12); //take from scilab ... why not ...
415             }
416
417             bool bFirst = ostemp.str().size() == 2;
418
419             df.bPrintPoint = false;
420             df.bPrintPlusSign = ostemp.str().size() != 2;
421             df.bPrintOne = i == 0;
422             addDoubleValue(&ostemp, _pdblVal[i], &df);
423
424             if (i != 0)
425             {
426                 ostemp << _szVar;
427                 piIndexExp[i] = static_cast<int>(ostemp.str().size());
428             }
429             ostemp << L" ";
430             iLen = static_cast<int>(ostemp.str().size());
431         }
432     }
433
434     if (iLastFlush != 0)
435     {
436         for (int j = iLastFlush ; j < m_iRank ; j++)
437         {
438             if (piIndexExp[j] == 0)
439             {
440                 continue;
441             }
442
443             addSpaces(&ostemp2, piIndexExp[j] - static_cast<int>(ostemp2.str().size()));
444             if (isRealZero(_pdblVal[j]) == false)
445             {
446                 ostemp2 << j;
447             }
448         }
449
450         if (ostemp.str() == L"  ")
451         {
452             ostemp << L"  0";
453             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
454         }
455
456         if (ostemp2.str() == L"")
457         {
458             addSpaces(&ostemp2, static_cast<int>(ostemp.str().size()));
459         }
460
461         _pListExp->push_back(ostemp2.str());
462         _pListCoef->push_back(ostemp.str());
463     }
464
465     delete[] piIndexExp;
466     return;
467 }
468
469 bool SinglePoly::operator==(const InternalType& it)
470 {
471     if (const_cast<InternalType &>(it).isSinglePoly() == false)
472     {
473         return false;
474     }
475
476     SinglePoly* pP = const_cast<InternalType &>(it).getAs<SinglePoly>();
477
478     if (getRank() != pP->getRank())
479     {
480         return false;
481     }
482
483     return *(getCoef()) == *(pP->getCoef());
484 }
485
486 bool SinglePoly::operator!=(const InternalType& it)
487 {
488     return !(*this == it);
489 }
490
491 SinglePoly* SinglePoly::clone()
492 {
493     SinglePoly* pPoly = NULL;
494     double *pR = NULL;
495     if (isComplex())
496     {
497         double *pI = NULL;
498         pPoly = new SinglePoly(&pR, &pI, getRank());
499         pPoly->setCoef(getCoefReal(), getCoefImg());
500     }
501     else
502     {
503         pPoly = new SinglePoly(&pR, getRank());
504         pPoly->setCoef(getCoefReal(), NULL);
505     }
506     return pPoly;
507 }
508
509 SinglePoly* SinglePoly::conjugate()
510 {
511     SinglePoly* pPoly = NULL;
512     if (isComplex())
513     {
514         double *pR = NULL;
515         double *pI = NULL;
516         SinglePoly * pPoly = new SinglePoly(&pR, &pI, getRank());
517
518         Transposition::conjugate(getRank(), getCoefReal(), pR, getCoefImg(), pI);
519
520         return pPoly;
521     }
522     else
523     {
524         return clone();
525     }
526 }
527 }
528
529