2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
4 * Copyright (C) 2018 - Stéphane MOTTELET
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
8 * This file is hereby licensed under the terms of the GNU GPL v2.0,
9 * pursuant to article 5.3.4 of the CeCILL v.2.1.
10 * This file was originally licensed under the terms of the CeCILL v2.1,
11 * and continues to be available under such terms.
12 * For more information, see the COPYING file which you should have received
13 * along with this program.
21 #include "tostring_common.hxx"
22 #include "configvariable.hxx"
26 #include "sci_malloc.h"
27 #include "elem_common.h"
28 #include "os_string.h"
30 #include "charEncoding.h"
36 #define EXPOSANT_SIZE 2 //exposant symbol + exposant sign
38 //template <typename T>
39 //void GetIntFormat(T _TVal, int *_piWidth)
41 // *_piWidth = (int)(log10((double)_abs64(_TVal)) + 1);
44 //template <typename T>
45 //void AddIntValue(ostringstream *_postr, T _TVal, int _iWidth, bool bPrintPlusSign, bool bPrintOne)
47 // if(bPrintPlusSign == true)
49 // *_postr << (_TVal < 0 ? MINUS_STRING_INT : PLUS_STRING);
53 // *_postr << (_TVal < 0 ? MINUS_STRING_INT : NO_SIGN);
56 // configureStream(_postr, _iWidth, 0, ' ');
58 // if(bPrintOne == true || _TVal != 1)
60 // *_postr << right << _abs64(_TVal);
64 void addSign(std::wostringstream * _postr, double _dblVal, bool _bPrintPlusSign, bool _bPaddSign)
66 if (_bPrintPlusSign == true)
68 *_postr << (_dblVal < 0 ? MINUS_STRING : PLUS_STRING);
74 *_postr << (_dblVal < 0 ? MINUS_STRING : NO_SIGN);
78 *_postr << (_dblVal < 0 ? MINUS_STRING : L"");
83 //void getDoubleFormat(double _dblVal, int *_piWidth, int *_piPrec, /*in/out*/bool* _pExp)
84 void getDoubleFormat(double _dblVal, DoubleFormat * _pDF)
88 double dblAbs = std::fabs(_dblVal);
91 int iBlankSize = _pDF->bPrintBlank ? BLANK_SIZE : 0;
92 _pDF->iSignLen = _pDF->bPrintBlank ? SIGN_LENGTH + BLANK_SIZE : _pDF->iSignLen;
94 _pDF->bExp |= ConfigVariable::getFormatMode() == 0;
96 int iPrecNeeded = ConfigVariable::getFormatSize();
98 if (ISNAN(_dblVal) || !finite(_dblVal))
100 _pDF->iWidth = 4; //" nan" or " inf"
104 //get integer part and fractionnal part
105 dblDec = std::modf(dblAbs, &dblEnt);
107 //compute len of entire part
111 iNbDigit = (int)std::fabs(std::floor(std::log10(dblAbs)));
113 if (iNbDigit >= (iPrecNeeded - 2) || _pDF->bExp)
117 iTotalLen = iBlankSize + 1 /*integer before dot */ + POINT_SIZE + EXPOSANT_SIZE + std::max(((int)log10((double)iNbDigit)) + 1, 2);
118 _pDF->iWidth = iPrecNeeded;
119 _pDF->iPrec = iPrecNeeded - iTotalLen;
124 iTotalLen = iBlankSize + 1 /*integer before dot */ + POINT_SIZE;
129 double dblTemp = log10(dblEnt);
131 if (dblTemp > (iPrecNeeded - 2) || _pDF->bExp)
136 dblTemp = 1; //no incidence on value, just to allow log10(dblTemp)
140 iTotalLen = iBlankSize + 1 /*integer before dot */ + POINT_SIZE + EXPOSANT_SIZE + std::max(((int)log10(dblTemp)) + 1, 2);
141 _pDF->iWidth = iPrecNeeded;
142 _pDF->iPrec = iPrecNeeded - iTotalLen;
147 //number of digit in integer part
148 iTotalLen = iBlankSize + ((int)dblTemp + 1) + POINT_SIZE;
152 //prepare fractionnal part to precision asked
153 double dblScale = pow(10., iPrecNeeded - iTotalLen);
154 while (iTotalLen <= iPrecNeeded)
156 dblDec = dblDec * dblScale;
157 dblDec = floor(dblDec + 0.5);
158 dblDec = dblDec / dblScale;
160 // when dblAbs = 1.9999999..., modf function
161 // return a decimal part equal to 1.0
162 if (dblDec == 0. || dblDec == 1.)
167 dblDec = dblDec * 10;
168 int iFloor = (int)floor(dblDec);
176 _pDF->iWidth = iTotalLen;
177 _pDF->iPrec = iNbDec;
180 //void getComplexFormat(double _dblR, double _dblI, int *_piTotalWidth, int *_piWidthR, int *_piWidthI, int *_piPrecR, int *_piPrecI, bool* _pExpR, bool* _pExpI)
181 void getComplexFormat(double _dblR, double _dblI, int *_piTotalWidth, DoubleFormat * _pDFR, DoubleFormat * _pDFI)
183 getDoubleFormat(_dblR, _pDFR);
184 getDoubleFormat(_dblI, _pDFI);
187 if (isRealZero(_dblI))
189 if (isRealZero(_dblR))
191 *_piTotalWidth += 1; //"0"
197 *_piTotalWidth += _pDFR->iWidth;
204 if (isRealZero(_dblR))
206 *_piTotalWidth += _pDFI->iWidth;
211 *_piTotalWidth += _pDFR->iWidth + _pDFI->iWidth;
219 void addDoubleValue(std::wostringstream * _postr, double _dblVal, DoubleFormat * _pDF)
221 wchar_t pwstFormat[32] = {0};
222 wchar_t pwstOutput[32] = {0}; // > @ format max
223 wchar_t pwstSign[32] = {0};
224 char pstBuf[32] = {0};
231 const wchar_t* pBlank = L"";
232 if (_pDF->bPrintBlank)
237 const wchar_t* pSign = MINUS_STRING;
238 if (_dblVal >= 0 || ISNAN(_dblVal))
240 if (_pDF->bPrintPlusSign)
244 else if (_pDF->bPaddSign)
250 // PLUS_SIGN "+" is not written by default
255 // Step 1: BLANK and SIGN in pwstSign
256 if (_pDF->bPrintComplexPlusSpace)
258 os_swprintf(pwstSign, 32, L"%ls%ls%ls", pBlank, pSign, pBlank);
262 os_swprintf(pwstSign, 32, L"%ls%ls", pBlank, pSign);
269 os_swprintf(pwstOutput, 32, L"%ls%-*ls", pwstSign, _pDF->iWidth - 1, L"Nan");
271 else if (!finite(_dblVal))
274 os_swprintf(pwstOutput, 32, L"%ls%-*ls", pwstSign, _pDF->iWidth - 1, L"Inf");
278 // Prints the exponent part 1.543D+03 for example
281 char *pRve = nullptr;
282 char *pDtoaStr = dtoa(fabs(_dblVal), 2, _pDF->iPrec + 1, &iDecpt, &iSign, &pRve);
284 std::string str(pDtoaStr);
287 // in format("e") omiting the decimal point has a sense
288 // only if fabs(_dblVal) is an integer in {1...9}
289 if (_pDF->bPrintPoint || str.length() > 1)
291 /* add trailing zeros */
292 str.append(fmax(0, _pDF->iPrec + 1 - str.length()), '0');
296 wchar_t* pwstData = to_wide_string(str.data());
297 os_swprintf(pwstOutput, 32, L"%ls%lsD%+.02d", pwstSign, pwstData, iDecpt - 1);
300 else if ((_pDF->bPrintOne == true) || (isEqual(fabs(_dblVal), 1)) == false)
302 //do not print if _bPrintOne == false && _dblVal == 1
305 int iWidth = _pDF->iWidth;
306 char *pRve = nullptr;
307 char *pDtoaStr = dtoa(fabs(_dblVal), 2, std::floor(log10(fabs(_dblVal))) + _pDF->iPrec + 1, &iDecpt, &iSign, &pRve);
309 std::string str(pDtoaStr);
312 /* add leading 0.000..., if applicable */
315 str.insert(str.begin(), 1 - iDecpt, '0');
318 else if (_pDF->bPrintPoint || iDecpt < (int)str.length())
320 str.append(std::max(0, (iDecpt - (int)str.length())), '0');
321 str.insert(iDecpt, ".");
325 str.append(std::max(0, (iDecpt - (int)str.length())), '0');
329 // append trailing zeros, if applicable
330 if (std::atof(str.data()) != fabs(_dblVal))
332 if (_pDF->bPrintPoint)
334 /* str.append(std::max(0, (ConfigVariable::getFormatSize() - (int)str.length()))-1, '0'); */
338 iWidth = 1+str.length();
342 wchar_t* pwstData = to_wide_string(str.data());
343 os_swprintf(pwstOutput, 32, L"%ls%-*ls", pwstSign, iWidth-1, pwstData);
346 else if (wcslen(pwstSign) != 0)
348 os_swprintf(pwstOutput, 32, L"%ls", pwstSign);
351 *_postr << pwstOutput;
355 void addDoubleValue(std::wostringstream *_postr, double _dblVal, int _iWidth, int _iPrec, bool bPrintPlusSign, bool bPrintOne, bool bPaddSign)
357 addSign(_postr, _dblVal, bPrintPlusSign, bPaddSign);
358 configureStream(_postr, _iWidth, _iPrec, ' ');
360 if(bPrintOne == true || isEqual(_dblVal, 1) == false)
362 NEWprintDoubleVar(_postr, _dblVal, _iWidth, _iPrec);
366 void addDoubleComplexValue(std::wostringstream * _postr, double _dblR, double _dblI, int _iTotalWidth, DoubleFormat * _pDFR, DoubleFormat * _pDFI)
368 std::wostringstream ostemp;
372 * if R && C -> R + Ci
377 // *_postr << "|%" << _iTotalWitdh << "%|";
388 addDoubleValue(&ostemp, 0, &df);
398 df.iPrec = _pDFI->iPrec;
399 df.bExp = _pDFI->bExp;
400 df.bPrintPlusSign = false;
401 df.bPrintOne = false;
402 addDoubleValue(&ostemp, _dblI, &df);
403 ostemp << std::left << SYMBOL_I;
406 addSpaces(&ostemp, 1);
422 df.iPrec = _pDFR->iPrec;
423 df.bExp = _pDFR->bExp;
424 addDoubleValue(&ostemp, _dblR, &df);
433 df.iPrec = _pDFR->iPrec;
434 df.bExp = _pDFR->bExp;
436 addDoubleValue(&ostemp, _dblR, &df);
439 df.iPrec = _pDFI->iPrec;
440 df.bExp = _pDFI->bExp;
441 df.bPrintPlusSign = true;
442 df.bPrintComplexPlusSpace = true;
443 df.bPrintOne = false;
445 addDoubleValue(&ostemp, _dblI, &df);
446 ostemp << std::left << SYMBOL_I;
449 addSpaces(&ostemp, 2);
454 configureStream(_postr, _iTotalWidth, 0, ' ');
455 *_postr << std::left << ostemp.str() << std::resetiosflags(std::ios::adjustfield);
458 void addSpaces(std::wostringstream * _postr, int _iSpace)
460 for (int i = 0; i < _iSpace; i++)
466 void configureStream(std::wostringstream * _postr, int _iWidth, int _iPrec, char _cFill)
468 _postr->setf(std::ios::showpoint);
469 _postr->width(_iWidth);
470 _postr->precision(_iPrec);
471 _postr->fill(_cFill);
474 void addColumnString(std::wostringstream& ostr, int _iFrom, int _iTo)
478 ostr << std::endl << L" column " << _iFrom << std::endl << std::endl;
482 ostr << std::endl << L" column " << _iFrom << L" to " << _iTo << std::endl << std::endl;
486 void printEmptyString(std::wostringstream& ostr)
491 void printDoubleValue(std::wostringstream& ostr, double val)
494 getDoubleFormat(val, &df);
495 ostr << SPACE_BETWEEN_TWO_VALUES;
496 addDoubleValue(&ostr, val, &df);
499 void printComplexValue(std::wostringstream& ostr, double val_r, double val_i)
501 DoubleFormat dfR, dfI;
502 getDoubleFormat(ZeroIsZero(val_r), &dfR);
503 getDoubleFormat(ZeroIsZero(val_i), &dfI);
504 ostr << SPACE_BETWEEN_TWO_VALUES;
505 addDoubleComplexValue(&ostr, ZeroIsZero(val_r), ZeroIsZero(val_i), dfR.iWidth + dfI.iWidth, &dfR, &dfI);