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