1 /*$Id: l_ftos.cc,v 1.3 2010-08-16 12:23:30 felix Exp $ -*- C++ -*-
3 * Copyright (C) 2001 Albert Davis
4 * Author: Albert Davis <aldavis@gnu.org>
6 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 *------------------------------------------------------------------
24 * builds string representing floating number
25 * num = number to convert.
26 * str = string to put it in. Must be big enough, or else!!
27 * Must have length at least len+6.
28 * sig digits + dec.pt.(1) + sign(1) + exp(4)
29 * len = max number of displayed digits. (left + right of dp)
30 * (includes d.p. if 'e' notation and 2 digit exp)
31 * fmt = format : 0 = alpha for exp notation
32 * FMTEXP = exponential notation
33 * FMTSIGN = always inlcude sign
34 * FMTFILL = fill in zeros
36 * returns a pointer to static space where the string is.
37 * there is a finite pool, so repeated calls work, to a point.
38 * after that, the space is overwritten, every POOLSIZE calls
40 //testing=script 2005.10.11
43 /*--------------------------------------------------------------------------*/
44 char* ftos(double,int,int,int);
45 /*--------------------------------------------------------------------------*/
46 const int POOLSIZE
= 100;
47 const int MAXLENGTH
= 40;
48 static double ftos_floor
= 1e-99;
49 /*--------------------------------------------------------------------------*/
50 std::string
to_string(std::string s
)
54 /*--------------------------------------------------------------------------*/
55 std::string
to_string(unsigned n
)
61 /*--------------------------------------------------------------------------*/
62 string
to_string(unsigned long int n
)
65 sprintf(s
, "%d", (int)n
);
68 /*--------------------------------------------------------------------------*/
69 string
to_string(int n
)
75 /*--------------------------------------------------------------------------*/
76 string
to_string(long int n
)
82 /*--------------------------------------------------------------------------*/
83 string
to_string(std::vector
<double> n
)
86 // FIXME: remove one ,
87 if (n
.size()==0){return "( )";}
89 std::vector
<double>::iterator i
=n
.begin();
90 buf
+= string("(") + ftos((double)*i
, 0, 7, 0);
94 buf
+= std::string(",") + ftos((double)*i
, 0, 7, 0);
97 return buf
+ std::string(" )");;
99 /*--------------------------------------------------------------------------*/
100 std::string
to_string(std::list
<double> n
)
102 trace1("to_string(list", n
.size());
104 // FIXME: remove one ,
105 for(std::list
<double>::iterator i
=n
.begin();
107 buf
+= std::string(", ") + ftos((double)*i
, 0, 7, 0);
111 /*--------------------------------------------------------------------------*/
112 std::string
to_string(double n
)
114 return ftos((double)n
, 0, 7, 0);
116 /*--------------------------------------------------------------------------*/
117 std::string
to_string(long double n
)
119 return ftos((double)n
, 0, 7, 0);
121 /*--------------------------------------------------------------------------*/
123 std::string
to_string(T n
)
125 return ftos((double)n
, 0, 7, 0);
127 /*--------------------------------------------------------------------------*/
128 char* ftos(double num
, int fieldwidth
, int len
, int fmt
)
129 // num = number to convert
130 // fieldwidth = size for fixed width, 0 for variable width
131 // len = max length of new string
132 // fmt = how to format it
138 if (len
> MAXLENGTH
-6) {
142 if (fieldwidth
> MAXLENGTH
-1) {
144 fieldwidth
= MAXLENGTH
-1;
148 { /* get a buffer from the pool */
149 //BUG// It is possible to have too many buffers active
150 // then the extras are overwritten, giving bad output
151 // There are no known cases, but it is not checked.
152 static char strpool
[POOLSIZE
][MAXLENGTH
];
153 static int poolindex
= 0;
155 if (poolindex
>= POOLSIZE
) {
158 str
= strpool
[poolindex
];
161 { /* build a clean blank string */
162 int string_size
= std::max(fieldwidth
, len
+6);
163 for (int iii
=0; iii
<string_size
; ++iii
) {
166 for (int iii
=string_size
; iii
<MAXLENGTH
; ++iii
) {
171 #ifdef HAS_NUMERIC_LIMITS
172 if (num
== std::numeric_limits
<double>::infinity()) {
174 strncpy(str
," Over", 5);
175 }else if (num
== -std::numeric_limits
<double>::infinity()) {
177 strncpy(str
,"-Over", 5);
178 }else if (num
== std::numeric_limits
<double>::quiet_NaN()) {
180 strncpy(str
," nan", 4);
181 }else if (num
== std::numeric_limits
<double>::signaling_NaN()) {
183 strncpy(str
," nan", 4);
186 trace1("ftos ", num
);
187 if (num
== NOT_VALID
) {
188 strncpy(str
," ??", 3);
189 }else if (num
== NOT_INPUT
) {
190 strncpy(str
," NA", 3);
191 }else if (num
>= BIGBIG
) {
192 strncpy(str
," Inf", 4);
193 }else if (num
<= -BIGBIG
) {
194 strncpy(str
,"-Inf", 4);
195 }else if (num
!= num
) {
196 strncpy(str
," NaN", 4);
198 if (std::abs(num
) < ftos_floor
) { /* hide noise */
202 int expo
= 0; /* exponent */
203 int nnn
= 0; /* char counter -- pos in string */
206 nnn
= static_cast<int>(strlen(str
)); /* num==0 .. build string 0.000... */
211 }else{ /* num != 0 */
216 }else if (fmt
& ftos_SIGN
) {
220 assert(str
[0] == ' ');
223 { // scale to .001 - 1.0. adjust expo.
234 { // adjust len to compensate for length of printed exponent
235 if ((fmt
&ftos_EXP
&& expo
<-9) || expo
>10 || expo
<-16) {
236 --len
; /* one less digit if 'e' notation */
237 } /* and exp is 2 digits */
242 { // round to correct number of digits
243 double rnd
= .5 / pow(10., len
); /* find amt to add to round */
246 }else if (num
< .1) {
249 num
+= rnd
; /* add it */
251 num
*= .001; /* created an extra digit: rescale */
257 if (expo
== -3) { /* .001 is preferable to 1e-3 */
258 int flg
= 0; /* print in fixed point, no exponent*/
264 int digit
= static_cast<int>(floor(num
));
265 num
-= static_cast<double>(digit
);
266 str
[nnn
++] = static_cast<char>(digit
+ '0');
267 if ((flg
+= digit
)) {
273 for (int iii
=2; len
>0; --iii
) {/* mantissa */
274 num
*= 10.; /* get next digit */
275 int digit
= static_cast<int>(floor(num
));
276 num
-= static_cast<double>(digit
);/* subtract off last digit */
277 if ((flg
+= digit
)) { /* if int part !=0 */
278 str
[nnn
++]=static_cast<char>(digit
+'0');/*(not all zeros so far)*/
279 --len
; /* stuff the digit into the string */
281 if (iii
==0) { /* if we found the dec.pt. and */
282 str
[nnn
++] = '.'; /* haven't used up all the space */
283 } /* put a dec.pt. in the string */
289 assert(str
[nnn
] == ' ' || str
[nnn
] == '\0');
291 { // suppress trailing zeros
292 if (!(fmt
&ftos_FILL
)) {
293 while (str
[--nnn
]=='0') {
294 str
[nnn
] = static_cast<char>((nnn
< fieldwidth
) ? ' ' : '\0');
305 }else if (fmt
&ftos_EXP
|| expo
>10 || expo
<-16) {/* exponential format */
307 sprintf(&str
[nnn
], ((expo
< 100) ? "E%+-3d" : "E%3u"), expo
);
310 }else{ /* if letter-scale format */
311 str
[nnn
++] = "fpnum KMGT"[(expo
+15)/3];/* put the appropriate letter*/
312 } /* note that letter-scale is not valid */
313 /* for exp==-3 or exp not in -15..+12 */
314 /* this is trapped but letter-scale is also */
315 /* not valid if exp not divisible by 3. */
316 /* This is not trapped, since it supposedly */
318 if (str
[nnn
-1] == 'M') {
319 str
[nnn
++] = 'e'; /* Spice kluge "MEG" */
324 { // clean up trailing blanks
332 /*--------------------------------------------------------------------------*/
333 /*--------------------------------------------------------------------------*/
334 // vim:ts=8:sw=2:noet: