display of some types and lines function fixed.
[scilab.git] / scilab / modules / ast / src / cpp / types / tostring_common.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2009 - 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
13 #include <wchar.h>
14 #include <stdio.h>
15 #include <iostream>
16 #include <math.h>
17 #include "tostring_common.hxx"
18 #include "configvariable.hxx"
19
20 extern "C"
21 {
22 #include "elem_common.h"
23 #include "os_swprintf.h"
24 }
25
26 #define BLANK_SIZE 1
27 #define POINT_SIZE 1
28 #define EXPOSANT_SIZE 2         //exposant symbol + exposant sign
29
30 using namespace std;
31
32 //template <typename T>
33 //void GetIntFormat(T _TVal, int *_piWidth)
34 //{
35 // *_piWidth = (int)(log10((double)_abs64(_TVal)) + 1);
36 //}
37
38 //template <typename T>
39 //void AddIntValue(ostringstream *_postr, T _TVal, int _iWidth, bool bPrintPlusSign, bool bPrintOne)
40 //{
41 // if(bPrintPlusSign == true)
42 // {
43 //  *_postr << (_TVal < 0 ? MINUS_STRING_INT : PLUS_STRING);
44 // }
45 // else
46 // {
47 //  *_postr << (_TVal < 0 ? MINUS_STRING_INT : NO_SIGN);
48 // }
49 //
50 // configureStream(_postr, _iWidth, 0, ' ');
51 //
52 // if(bPrintOne == true || _TVal != 1)
53 // {
54 //  *_postr << right << _abs64(_TVal);
55 // }
56 //}
57
58 void addSign(wostringstream * _postr, double _dblVal, bool _bPrintPlusSign, bool _bPaddSign)
59 {
60     if (_bPrintPlusSign == true)
61     {
62         *_postr << (_dblVal < 0 ? MINUS_STRING : PLUS_STRING);
63     }
64     else
65     {
66         if (_bPaddSign)
67         {
68             *_postr << (_dblVal < 0 ? MINUS_STRING : NO_SIGN);
69         }
70         else
71         {
72             *_postr << (_dblVal < 0 ? MINUS_STRING : L"");
73         }
74     }
75 }
76
77 //void getDoubleFormat(double _dblVal, int *_piWidth, int *_piPrec, /*in/out*/bool* _pExp)
78 void getDoubleFormat(double _dblVal, DoubleFormat * _pDF)
79 {
80     double dblDec = 0;
81     double dblEnt = 0;
82     double dblAbs = fabs(_dblVal);
83     int iNbDigit = 0;
84     int iNbDec = 0;
85     int iBlankSize = _pDF->bPrintBlank ? BLANK_SIZE : 0;
86     _pDF->iSignLen = _pDF->bPrintBlank ? _pDF->iSignLen + 1 : _pDF->iSignLen;
87
88     _pDF->bExp |= ConfigVariable::getFormatMode() == 0;
89     int iTotalLen = 0;
90     int iPrecNeeded = ConfigVariable::getFormatSize();
91
92     if (ISNAN(_dblVal) || !finite(_dblVal))
93     {
94         _pDF->iWidth = 5;      //" nan" or " inf"
95         _pDF->iPrec = 0;
96         return;
97     }
98     //get integer part and fractionnal part
99     dblDec = modf(dblAbs, &dblEnt);
100
101     //compute len of entire part
102     if (dblEnt == 0)
103     {
104         //[-1, 1]
105         iNbDigit = (int)fabs(floor(log10(dblAbs)));
106
107         if (iNbDigit >= (iPrecNeeded - 2) || _pDF->bExp)
108         {
109             //exponant
110             _pDF->bExp = true;
111             iTotalLen = iBlankSize + 1 /*integer before dot */  + POINT_SIZE + EXPOSANT_SIZE + std::max((int)log10((double)iNbDigit), 2);
112             _pDF->iWidth = iPrecNeeded;
113             _pDF->iPrec = iPrecNeeded - iTotalLen;
114             return;
115         }
116         else
117         {
118             iTotalLen = iBlankSize + 1 /*integer before dot */  + POINT_SIZE;
119         }
120     }
121     else
122     {
123         double dblTemp = log10(dblEnt);
124
125         if (dblTemp > (iPrecNeeded - 2) || _pDF->bExp)
126         {
127             //exponant mode
128             if (dblTemp == 0)
129             {
130                 dblTemp = 1;    //no incidence on value, just to allow log10(dblTemp)
131             }
132
133             _pDF->bExp = true;
134             iTotalLen = iBlankSize + 1 /*integer before dot */  + POINT_SIZE + EXPOSANT_SIZE + std::max((int)log10(dblTemp), 2);
135             _pDF->iWidth = iPrecNeeded;
136             _pDF->iPrec = iPrecNeeded - iTotalLen;
137             return;
138         }
139         else
140         {
141             //number of digit in integer part
142             iTotalLen = iBlankSize + ((int)dblTemp + 1) + POINT_SIZE;
143         }
144     }
145
146     //prepare fractionnal part to precision asked
147     double dblScale = pow(10., iPrecNeeded - iTotalLen);
148     while (iTotalLen <= iPrecNeeded)
149     {
150         dblDec = dblDec * dblScale;
151         dblDec = floor(dblDec + 0.5);
152         dblDec = dblDec / dblScale;
153
154         // when dblAbs = 1.9999999..., modf function
155         // return a decimal part equal to 1.0
156         if (dblDec == 0. || dblDec == 1.)
157         {
158             break;
159         }
160
161         dblDec = dblDec * 10;
162         int iFloor = (int)floor(dblDec);
163
164         dblDec -= iFloor;
165         iTotalLen++;
166         iNbDec++;
167         dblScale /= 10;
168     }
169
170     _pDF->iWidth = iTotalLen;
171     _pDF->iPrec = iNbDec;
172 }
173
174 //void getComplexFormat(double _dblR, double _dblI, int *_piTotalWidth, int *_piWidthR, int *_piWidthI, int *_piPrecR, int *_piPrecI, bool* _pExpR, bool* _pExpI)
175 void getComplexFormat(double _dblR, double _dblI, int *_piTotalWidth, DoubleFormat * _pDFR, DoubleFormat * _pDFI)
176 {
177     getDoubleFormat(_dblR, _pDFR);
178     getDoubleFormat(_dblI, _pDFI);
179
180     *_piTotalWidth = 0;
181     if (isRealZero(_dblI))
182     {
183         if (isRealZero(_dblR))
184         {
185             *_piTotalWidth += 1;    //"0"
186             _pDFI->iWidth = 0;
187             _pDFI->iSignLen = 0;
188         }
189         else
190         {
191             *_piTotalWidth += _pDFR->iWidth + _pDFR->iSignLen;
192             _pDFI->iWidth = 0;
193             _pDFI->iSignLen = 0;
194         }
195     }
196     else
197     {
198         if (isRealZero(_dblR))
199         {
200             *_piTotalWidth += _pDFI->iWidth + _pDFI->iSignLen;
201             _pDFR->iWidth = 0;
202         }
203         else
204         {
205             *_piTotalWidth += _pDFR->iWidth + _pDFR->iSignLen + _pDFI->iWidth + _pDFI->iSignLen;
206         }
207
208         // i character
209         _pDFI->iWidth += 1;
210         *_piTotalWidth += 1;
211     }
212 }
213
214 void addDoubleValue(std::wostringstream * _postr, double _dblVal, DoubleFormat * _pDF)
215 {
216     wchar_t pwstFormat[32] = {0};
217     wchar_t pwstOutput[32] = {0};     // > @ format max
218     wchar_t pwstSign[32] = {0};
219
220     if (_pDF == NULL)
221     {
222         return;
223     }
224
225     const wchar_t* pBlank = L"";
226     if (_pDF->bPrintBlank)
227     {
228         pBlank = L" ";
229     }
230
231     const wchar_t* pSign = MINUS_STRING;
232     if (_dblVal >= 0 || ISNAN(_dblVal))
233     {
234         if (_pDF->bPrintPlusSign)
235         {
236             pSign = PLUS_STRING;
237         }
238         else if (_pDF->bPaddSign)
239         {
240             pSign = NO_SIGN;
241         }
242         else
243         {
244             pSign = L"";
245         }
246     }
247
248     os_swprintf(pwstSign, 32, L"%ls%ls%ls", pBlank, pSign, pBlank);
249
250     if (ISNAN(_dblVal))
251     {
252         //NaN
253         os_swprintf(pwstOutput, 32, L"%ls%*ls", pwstSign, _pDF->iPrec, L"Nan");
254     }
255     else if (!finite(_dblVal))
256     {
257         //Inf
258         os_swprintf(pwstOutput, 32, L"%ls%*ls", pwstSign, _pDF->iPrec, L"Inf");
259     }
260     else if (_pDF->bExp)
261     {
262         double dblAbs = fabs(_dblVal);
263         double dblDec = 0;
264         double dblEnt = 0;
265         double dblTemp = 0;
266
267         dblDec = modf(dblAbs, &dblEnt);
268         if (dblEnt == 0)
269         {
270             dblTemp = floor(log10(dblDec));
271         }
272         else
273         {
274             dblTemp = log10(dblEnt);
275         }
276
277         dblDec = dblAbs / pow(10., (double)(int)dblTemp);
278         dblDec = modf(dblDec, &dblEnt) * pow(10., _pDF->iPrec);
279
280         if (_pDF->bPrintPoint)
281         {
282             os_swprintf(pwstFormat, 32, L"%ls%%#.0f%%0%d.0fD%%+.02d", pwstSign, _pDF->iPrec);
283         }
284         else
285         {
286             os_swprintf(pwstFormat, 32, L"%ls%%.0f%%0%d.0fD%%+.02d", pwstSign, _pDF->iPrec);
287         }
288
289         os_swprintf(pwstOutput, 32, pwstFormat, dblEnt, dblDec, (int)dblTemp);
290     }
291     else if ((_pDF->bPrintOne == true) || (isEqual(fabs(_dblVal), 1)) == false)
292     {
293         //do not print if _bPrintOne == false && _dblVal == 1
294         if (_pDF->bPrintPoint)
295         {
296             os_swprintf(pwstFormat, 32, L"%ls%%#-%d.%df", pwstSign, _pDF->iWidth - 1, _pDF->iPrec);
297         }
298         else
299         {
300             os_swprintf(pwstFormat, 32, L"%ls%%-%d.%df", pwstSign, _pDF->iWidth - 2, _pDF->iPrec);  //-2 no point needed
301         }
302
303         os_swprintf(pwstOutput, 32, pwstFormat, fabs(_dblVal));
304     }
305     else if (wcslen(pwstSign) != 0)
306     {
307         os_swprintf(pwstOutput, 32, L"%ls", pwstSign);
308     }
309
310     *_postr << pwstOutput;
311 }
312
313 /*
314 void addDoubleValue(wostringstream *_postr, double _dblVal, int _iWidth, int _iPrec, bool bPrintPlusSign, bool bPrintOne, bool bPaddSign)
315 {
316     addSign(_postr, _dblVal, bPrintPlusSign, bPaddSign);
317     configureStream(_postr, _iWidth, _iPrec, ' ');
318
319     if(bPrintOne == true || isEqual(_dblVal, 1) == false)
320     {
321         NEWprintDoubleVar(_postr, _dblVal, _iWidth, _iPrec);
322     }
323 }
324 */
325 void addDoubleComplexValue(wostringstream * _postr, double _dblR, double _dblI, int _iTotalWidth, DoubleFormat * _pDFR, DoubleFormat * _pDFI)
326 {
327     wostringstream ostemp;
328
329     /*
330      * if R && !C -> R
331      * if R && C -> R + Ci
332      * if !R && !C -> 0
333      * if(!R && C -> Ci
334      */
335
336     // *_postr << "|%" << _iTotalWitdh << "%|";
337     if (_dblR == 0)
338     {
339         //no real part
340         if (_dblI == 0)
341         {
342             //no imaginary part
343
344             //0
345             DoubleFormat df;
346
347             addDoubleValue(&ostemp, 0, &df);
348         }
349         else
350         {
351             //imaginary part
352
353             //I
354             DoubleFormat df;
355
356             df.iWidth = 0;
357             df.iPrec = _pDFI->iPrec;
358             df.bExp = _pDFI->bExp;
359             df.bPrintPlusSign = false;
360             df.bPrintOne = false;
361             addDoubleValue(&ostemp, _dblI, &df);
362             ostemp << left << SYMBOL_I;
363             if (_dblI == 1)
364             {
365                 addSpaces(&ostemp, 2);
366             }
367
368         }
369     }
370     else
371     {
372         //real part
373         if (_dblI == 0)
374         {
375             //no imaginary part
376
377             //R
378             DoubleFormat df;
379
380             df.iWidth = 0;
381             df.iPrec = _pDFR->iPrec;
382             df.bExp = _pDFR->bExp;
383             addDoubleValue(&ostemp, _dblR, &df);
384         }
385         else
386         {
387             //imaginary part
388
389             //R
390             DoubleFormat df;
391
392             df.iPrec = _pDFR->iPrec;
393             df.bExp = _pDFR->bExp;
394
395             addDoubleValue(&ostemp, _dblR, &df);
396
397             //I
398             df.iPrec = _pDFI->iPrec;
399             df.bExp = _pDFI->bExp;
400             df.bPrintPlusSign = true;
401             df.bPrintOne = false;
402
403             addDoubleValue(&ostemp, _dblI, &df);
404             ostemp << left << SYMBOL_I;
405             if (_dblI == 1)
406             {
407                 addSpaces(&ostemp, 2);
408             }
409         }
410     }
411
412     configureStream(_postr, _iTotalWidth - 3, 0, ' ');
413     *_postr << left << ostemp.str();
414 }
415
416 void addSpaces(wostringstream * _postr, int _iSpace)
417 {
418     for (int i = 0; i < _iSpace; i++)
419     {
420         *_postr << L" ";
421     }
422 }
423
424 void configureStream(wostringstream * _postr, int _iWidth, int _iPrec, char _cFill)
425 {
426     _postr->setf(ios::showpoint);
427     _postr->width(_iWidth);
428     _postr->precision(_iPrec);
429     _postr->fill(_cFill);
430 }
431
432 void addColumnString(std::wostringstream& ostr, int _iFrom, int _iTo)
433 {
434     if (_iFrom == _iTo)
435     {
436         ostr << std::endl << L"         column " << _iFrom << std::endl << std::endl;
437     }
438     else
439     {
440         ostr << std::endl << L"         column " << _iFrom << L" to " << _iTo << std::endl << std::endl;
441     }
442 }