annotate gsm-fw/sprintf/float.c @ 192:707aa640b2dc

fc-tmsh: w8/w16/w32 implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 25 Nov 2013 05:37:46 +0000
parents 4ac657b95f52
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
146
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
1 /*
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
2 * Embedded [v]sprintf() implementation by Michael Spacefalcon,
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
3 * loosely based on the 4.3BSD-Tahoe version.
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
4 *
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
5 * This module contains the floating point conversion functions.
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
6 */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
7
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
8 #include <sys/types.h>
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
9 #include <ctype.h>
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
10 #include "defs.h"
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
11
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
12 extern double modf();
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
13
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
14 extern u_char * _sprintf_field(u_char *op, int width, int flags, int sign,
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
15 u_char *body, int size, int dprec, int fpprec);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
16
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
17 #define MAX_INT_DIGITS 10 /* 2^32-1 in decimal */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
18 #define MAXFRACT 16 /* max sensible for 64-bit double */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
19 #define DEFPREC 6
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
20
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
21 static char *
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
22 emit_integer_portion(unsigned number, char *endp)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
23 {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
24 char *t = endp;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
25
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
26 do {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
27 *--t = tochar(number % 10);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
28 number /= 10;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
29 } while (number);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
30 return (t);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
31 }
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
32
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
33 static int
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
34 f_round(double fract, char *start, char *end, int sign)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
35 {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
36 double tmp;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
37
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
38 (void)modf(fract * 10, &tmp);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
39 if (tmp > 4)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
40 for (;; --end) {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
41 if (*end == '.')
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
42 --end;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
43 if (++*end <= '9')
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
44 break;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
45 *end = '0';
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
46 }
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
47 /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
48 else if (sign == '-')
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
49 for (;; --end) {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
50 if (*end == '.')
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
51 --end;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
52 if (*end != '0')
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
53 break;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
54 if (end == start)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
55 return(1); /* clear the -ve */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
56 }
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
57 return(0);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
58 }
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
59
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
60 u_char *
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
61 _sprintf_percent_f(u_char *op, int width, int flags, int sign,
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
62 double number, int prec)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
63 {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
64 char buf[MAX_INT_DIGITS + 1 + MAXFRACT];
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
65 int extra_prec = 0;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
66 int origsign = sign;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
67 double fract, tmp;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
68 char *start, *t;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
69
147
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
70 /* first order of business: weed out infinities and NaNs */
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
71 if (isinf(number)) {
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
72 if (number < 0)
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
73 sign = '-';
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
74 return _sprintf_field(op, width, flags, sign, "Inf", 3, 0, 0);
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
75 }
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
76 if (isnan(number))
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
77 return _sprintf_field(op, width, flags, sign, "NaN", 3, 0, 0);
4ac657b95f52 gsm-fw: sprintf %f: handle infinities and NaNs
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents: 146
diff changeset
78 /* OK, we know it's a valid real like in the good old VAX days */
146
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
79 if (number < 0) {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
80 sign = '-';
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
81 number = -number;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
82 }
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
83 fract = modf(number, &tmp);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
84 if (tmp > (double) 0xFFFFFFFF)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
85 return _sprintf_field(op, width, flags, sign, "Toobig", 6,
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
86 0, 0);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
87 start = emit_integer_portion((unsigned) tmp, buf + MAX_INT_DIGITS);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
88 if (prec > MAXFRACT) {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
89 extra_prec = prec - MAXFRACT;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
90 prec = MAXFRACT;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
91 } else if (prec == -1)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
92 prec = DEFPREC;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
93 t = buf + MAX_INT_DIGITS;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
94 /*
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
95 * if precision required or alternate flag set, add in a
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
96 * decimal point.
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
97 */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
98 if (prec || flags&ALT)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
99 *t++ = '.';
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
100 /* if requires more precision and some fraction left */
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
101 if (fract) {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
102 if (prec)
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
103 do {
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
104 fract = modf(fract * 10, &tmp);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
105 *t++ = tochar((int)tmp);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
106 } while (--prec && fract);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
107 if (fract && f_round(fract, start, t - 1, sign))
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
108 sign = origsign;
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
109 }
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
110 return _sprintf_field(op, width, flags, sign, start, t - start,
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
111 0, prec + extra_prec);
4d629b6bbcfd gsm-fw/sprintf: %f implemented, debug output looks correct
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
112 }