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