00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 module mango.format.Double;
00040
00041 private import mango.format.Int,
00042 mango.format.Styled;
00043
00044 extern (C) double frexp (double, int*);
00045
00046 version (Posix)
00047 {
00048 extern (C) int strncasecmp (char *, char*, uint);
00049 alias strncasecmp memicmp;
00050 }
00051 else
00052 extern (C) int memicmp (char*, char*, uint);
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 class Double : Styled
00068 {
00069 alias double tValue;
00070
00071
00072
00073
00074
00075
00076
00077
00078 private static tValue pow10 (uint exp)
00079 in {
00080 assert (exp < 512);
00081 }
00082 body
00083 {
00084 static tValue[] Powers =
00085 [
00086 1.0e1,
00087 1.0e2,
00088 1.0e4,
00089 1.0e8,
00090 1.0e16,
00091 1.0e32,
00092 1.0e64,
00093 1.0e128,
00094 1.0e256,
00095 ];
00096
00097 tValue mult = 1.0;
00098 foreach (tValue power; Powers)
00099 {
00100 if (exp & 1)
00101 mult *= power;
00102 if ((exp >>= 1) == 0)
00103 break;
00104 }
00105 return mult;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 final static tValue parse (char[] src, uint* ate=null)
00118 {
00119 char c;
00120 char* p;
00121 int exp;
00122 bool sign;
00123 tValue value = 0.0;
00124
00125
00126 c = *(p = src.ptr + Int.trim (src, sign));
00127
00128
00129
00130 while (c >= '0' && c <= '9')
00131 {
00132 value = value * 10 + (c - '0');
00133 c = *++p;
00134 }
00135
00136
00137 if (c == '.')
00138 c = *++p;
00139
00140
00141
00142
00143
00144
00145
00146
00147 while (c >= '0' && c <= '9')
00148 {
00149 value = value * 10 + (c - '0');
00150 c = *++p;
00151 --exp;
00152 }
00153
00154
00155 if (value)
00156 {
00157
00158 if (c == 'e' || c == 'E')
00159 {
00160 uint len;
00161 exp += Int.parse (src[(p-src.ptr)+1..length], 10, &len);
00162 p += len;
00163 }
00164
00165
00166
00167 if (exp < 0)
00168 value /= pow10 (-exp);
00169 else
00170 value *= pow10 (exp);
00171 }
00172 else
00173
00174 if (p == src.ptr)
00175 if (memicmp (p, "inf", 3) == 0)
00176 p += 3, value = tValue.infinity;
00177 else
00178 if (memicmp (p, "nan", 3) == 0)
00179 p += 3, value = tValue.nan;
00180
00181
00182 if (ate)
00183 *ate = p - src.ptr;
00184 return sign ? -value : value;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194 final static int format (double i, inout Style style)
00195 {
00196 return style.emit (format (style.workspace, i,
00197 (style.flags & Flags.Prec) ? style.precision : 6,
00198 style.type == 'e'));
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 static final char[] format (char[] dst, tValue x, uint decimals = 6, bool scientific = false)
00215 in {
00216 assert (dst.length >= 32);
00217 }
00218 body
00219 {
00220
00221
00222 static int toDigit (inout tValue v, inout int count)
00223 {
00224 int digit;
00225
00226
00227 if (++count > 17)
00228 digit = 0;
00229 else
00230 {
00231
00232 digit = cast(int) v;
00233 v = (v - digit) * 10.0;
00234 }
00235 return digit + '0';
00236 }
00237
00238
00239 if (((cast(ushort*) &x)[3] & 0x7ff0) == 0x7ff0)
00240 if (*(cast(ulong*) &x) & 0x000f_ffff_ffff_ffff)
00241 return "nan";
00242 else
00243 return "inf";
00244
00245 int exp;
00246 bool sign;
00247
00248
00249 if (x < 0.0)
00250 {
00251 x = -x;
00252 sign = true;
00253 }
00254
00255
00256 if (x > 0.0)
00257 {
00258
00259 x += 0.5 / pow10 (decimals);
00260
00261
00262 frexp (x, &exp);
00263 exp = cast(int) (0.301029995664 * exp);
00264
00265
00266 int len = exp;
00267 if (exp < 0)
00268 {
00269 --exp;
00270 x *= pow10 (len = -exp);
00271 }
00272 else
00273 x /= pow10 (exp);
00274
00275
00276 if (len + 32 > dst.length)
00277 scientific = true;
00278 }
00279
00280 char*p = dst;
00281 int count = 0;
00282
00283
00284 if (sign)
00285 *p++ = '-';
00286
00287
00288 if (scientific)
00289 {
00290
00291 *p++ = toDigit (x, count);
00292 *p++ = '.';
00293
00294
00295 while (decimals-- > 0)
00296 *p++ = toDigit (x, count);
00297
00298
00299 if (exp)
00300 {
00301 *p++ = 'e';
00302 *p++ = (exp < 0) ? '-' : '+';
00303 if (exp < 0)
00304 exp = -exp;
00305
00306 if (exp >= 100)
00307 {
00308 *p++ = (exp/100) + '0';
00309 exp %= 100;
00310 }
00311
00312 *p++ = (exp/10) + '0';
00313 *p++ = (exp%10) + '0';
00314 }
00315 }
00316 else
00317 {
00318
00319 if (exp < 0)
00320 *p++ = '0';
00321 else
00322
00323 for (; exp >= 0; --exp)
00324 *p++ = toDigit (x, count);
00325
00326
00327 *p++ = '.';
00328
00329
00330 for (++exp; exp < 0 && decimals > 0; --decimals, ++exp)
00331 *p++ = '0';
00332
00333
00334
00335 while (decimals-- > 0)
00336 *p++ = toDigit (x, count);
00337 }
00338
00339 return dst [0..(p - dst.ptr)];
00340 }
00341 }
00342
00343