ReactOS 0.4.15-dev-8241-g63935f8
i10output.c
Go to the documentation of this file.
1#include <precomp.h>
2
3// From Wine msvcrt.h
4typedef struct {ULONG x80[3];} MSVCRT__LDOUBLE; /* Intel 80 bit FP format has sizeof() 12 */
5enum fpmod {
6 FP_ROUND_ZERO, /* only used when dropped part contains only zeros */
12};
13struct fpnum {
14 int sign;
15 int exp;
17 enum fpmod mod;
18};
19
20// From wine bnum.h
21#define EXP_BITS 11
22#define MANT_BITS 53
23
24int fpnum_double(struct fpnum *fp, double *d)
25{
26 ULONGLONG bits = 0;
27
28 if (fp->mod == FP_VAL_INFINITY)
29 {
30 *d = fp->sign * INFINITY;
31 return 0;
32 }
33
34 if (fp->mod == FP_VAL_NAN)
35 {
36 bits = ~0;
37 if (fp->sign == 1)
38 bits &= ~((ULONGLONG)1 << (MANT_BITS + EXP_BITS - 1));
39 *d = *(double*)&bits;
40 return 0;
41 }
42
43 TRACE("%c %#I64x *2^%d (round %d)\n", fp->sign == -1 ? '-' : '+',
44 fp->m, fp->exp, fp->mod);
45 if (!fp->m)
46 {
47 *d = fp->sign * 0.0;
48 return 0;
49 }
50
51 /* make sure that we don't overflow modifying exponent */
52 if (fp->exp > 1<<EXP_BITS)
53 {
54 *d = fp->sign * INFINITY;
55 return ERANGE;
56 }
57 if (fp->exp < -(1<<EXP_BITS))
58 {
59 *d = fp->sign * 0.0;
60 return ERANGE;
61 }
62 fp->exp += MANT_BITS - 1;
63
64 /* normalize mantissa */
65 while(fp->m < (ULONGLONG)1 << (MANT_BITS-1))
66 {
67 fp->m <<= 1;
68 fp->exp--;
69 }
70 while(fp->m >= (ULONGLONG)1 << MANT_BITS)
71 {
72 if (fp->m & 1 || fp->mod != FP_ROUND_ZERO)
73 {
74 if (!(fp->m & 1)) fp->mod = FP_ROUND_DOWN;
75 else if(fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
76 else fp->mod = FP_ROUND_UP;
77 }
78 fp->m >>= 1;
79 fp->exp++;
80 }
81 fp->exp += (1 << (EXP_BITS-1)) - 1;
82
83 /* handle subnormals */
84 if (fp->exp <= 0)
85 {
86 if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
87 else if (fp->m & 1) fp->mod = FP_ROUND_UP;
88 else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN;
89 fp->m >>= 1;
90 }
91 while(fp->m && fp->exp<0)
92 {
93 if (fp->m & 1 && fp->mod == FP_ROUND_ZERO) fp->mod = FP_ROUND_EVEN;
94 else if (fp->m & 1) fp->mod = FP_ROUND_UP;
95 else if (fp->mod != FP_ROUND_ZERO) fp->mod = FP_ROUND_DOWN;
96 fp->m >>= 1;
97 fp->exp++;
98 }
99
100 /* round mantissa */
101 if (fp->mod == FP_ROUND_UP || (fp->mod == FP_ROUND_EVEN && fp->m & 1))
102 {
103 fp->m++;
104
105 /* handle subnormal that falls into regular range due to rounding */
106 if (fp->m == (ULONGLONG)1 << (MANT_BITS - 1))
107 {
108 fp->exp++;
109 }
110 else if (fp->m >= (ULONGLONG)1 << MANT_BITS)
111 {
112 fp->exp++;
113 fp->m >>= 1;
114 }
115 }
116
117 if (fp->exp >= (1<<EXP_BITS)-1)
118 {
119 *d = fp->sign * INFINITY;
120 return ERANGE;
121 }
122 if (!fp->m || fp->exp < 0)
123 {
124 *d = fp->sign * 0.0;
125 return ERANGE;
126 }
127
128 if (fp->sign == -1)
129 bits |= (ULONGLONG)1 << (MANT_BITS + EXP_BITS - 1);
130 bits |= (ULONGLONG)fp->exp << (MANT_BITS - 1);
131 bits |= fp->m & (((ULONGLONG)1 << (MANT_BITS - 1)) - 1);
132
133 TRACE("returning %#I64x\n", bits);
134 *d = *(double*)&bits;
135 return 0;
136}
137
138#define I10_OUTPUT_MAX_PREC 21
139/* Internal structure used by $I10_OUTPUT */
141 short pos;
142 char sign;
144 char str[I10_OUTPUT_MAX_PREC+1]; /* add space for '\0' */
145};
146
147/*********************************************************************
148 * $I10_OUTPUT (MSVCRT.@)
149 * ld80 - long double (Intel 80 bit FP in 12 bytes) to be printed to data
150 * prec - precision of part, we're interested in
151 * flag - 0 for first prec digits, 1 for fractional part
152 * data - data to be populated
153 *
154 * return value
155 * 0 if given double is NaN or INF
156 * 1 otherwise
157 *
158 * FIXME
159 * Native sets last byte of data->str to '0' or '9', I don't know what
160 * it means. Current implementation sets it always to '0'.
161 */
162int CDECL I10_OUTPUT(MSVCRT__LDOUBLE ld80, int prec, int flag, struct _I10_OUTPUT_DATA *data)
163{
164 struct fpnum num;
165 double d;
166 char format[8];
167 char buf[I10_OUTPUT_MAX_PREC+9]; /* 9 = strlen("0.e+0000") + '\0' */
168 char *p;
169
170 if ((ld80.x80[2] & 0x7fff) == 0x7fff)
171 {
172 if (ld80.x80[0] == 0 && ld80.x80[1] == 0x80000000)
173 strcpy( data->str, "1#INF" );
174 else
175 strcpy( data->str, (ld80.x80[1] & 0x40000000) ? "1#QNAN" : "1#SNAN" );
176 data->pos = 1;
177 data->sign = (ld80.x80[2] & 0x8000) ? '-' : ' ';
178 data->len = (BYTE)strlen(data->str);
179 return 0;
180 }
181
182 num.sign = (ld80.x80[2] & 0x8000) ? -1 : 1;
183 num.exp = (ld80.x80[2] & 0x7fff) - 0x3fff - 63;
184 num.m = ld80.x80[0] | ((ULONGLONG)ld80.x80[1] << 32);
185 num.mod = FP_ROUND_EVEN;
186 fpnum_double( &num, &d );
187 TRACE("(%lf %d %x %p)\n", d, prec, flag, data);
188
189 if(d<0) {
190 data->sign = '-';
191 d = -d;
192 } else
193 data->sign = ' ';
194
195 if(flag&1) {
196 int exp = 1 + floor(log10(d));
197
198 prec += exp;
199 if(exp < 0)
200 prec--;
201 }
202 prec--;
203
204 if(prec+1 > I10_OUTPUT_MAX_PREC)
205 prec = I10_OUTPUT_MAX_PREC-1;
206 else if(prec < 0) {
207 d = 0.0;
208 prec = 0;
209 }
210
211 sprintf_s(format, sizeof(format), "%%.%dle", prec);
212 sprintf_s(buf, sizeof(buf), format, d);
213
214 buf[1] = buf[0];
215 data->pos = atoi(buf+prec+3);
216 if(buf[1] != '0')
217 data->pos++;
218
219 for(p = buf+prec+1; p>buf+1 && *p=='0'; p--);
220 data->len = p-buf;
221
222 memcpy(data->str, buf+1, data->len);
223 data->str[data->len] = '\0';
224
225 if(buf[1]!='0' && prec-data->len+1>0)
226 memcpy(data->str+data->len+1, buf+data->len+1, prec-data->len+1);
227
228 return 1;
229}
230#undef I10_OUTPUT_MAX_PREC
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ERANGE
Definition: acclib.h:92
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define CDECL
Definition: compat.h:29
double log10(double x)
Definition: freeldr.c:125
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
#define EXP_BITS
Definition: i10output.c:21
#define MANT_BITS
Definition: i10output.c:22
int fpnum_double(struct fpnum *fp, double *d)
Definition: i10output.c:24
#define I10_OUTPUT_MAX_PREC
Definition: i10output.c:138
int CDECL I10_OUTPUT(MSVCRT__LDOUBLE ld80, int prec, int flag, struct _I10_OUTPUT_DATA *data)
Definition: i10output.c:162
fpmod
Definition: i10output.c:5
@ FP_VAL_NAN
Definition: i10output.c:11
@ FP_ROUND_EVEN
Definition: i10output.c:8
@ FP_VAL_INFINITY
Definition: i10output.c:10
@ FP_ROUND_UP
Definition: i10output.c:9
@ FP_ROUND_ZERO
Definition: i10output.c:6
@ FP_ROUND_DOWN
Definition: i10output.c:7
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define d
Definition: ke_i.h:81
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define INFINITY
Definition: misc.c:36
DWORD exp
Definition: msg.c:16058
#define TRACE(s)
Definition: solgame.cpp:4
ULONG x80[3]
Definition: msvcrt.h:91
char str[I10_OUTPUT_MAX_PREC+1]
Definition: i10output.c:144
enum fpmod mod
Definition: i10output.c:17
ULONGLONG m
Definition: i10output.c:16
int exp
Definition: i10output.c:15
int sign
Definition: i10output.c:14
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
unsigned char BYTE
Definition: xxhash.c:193