1 | /* Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
|
---|
2 | This file is part of the GNU C Library.
|
---|
3 |
|
---|
4 | The GNU C Library is free software; you can redistribute it and/or
|
---|
5 | modify it under the terms of the GNU Lesser General Public
|
---|
6 | License as published by the Free Software Foundation; either
|
---|
7 | version 2.1 of the License, or (at your option) any later version.
|
---|
8 |
|
---|
9 | The GNU C Library is distributed in the hope that it will be useful,
|
---|
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
12 | Lesser General Public License for more details.
|
---|
13 |
|
---|
14 | You should have received a copy of the GNU Lesser General Public
|
---|
15 | License along with the GNU C Library; if not, write to the Free
|
---|
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
---|
17 | 02111-1307 USA. */
|
---|
18 |
|
---|
19 | #ifndef _GNU_SOURCE
|
---|
20 | # define _GNU_SOURCE 1
|
---|
21 | #endif
|
---|
22 |
|
---|
23 | #include <float.h>
|
---|
24 | #include <math.h>
|
---|
25 | #include <stdio.h>
|
---|
26 | #include <stdlib.h>
|
---|
27 | #include <string.h>
|
---|
28 |
|
---|
29 | int error_count;
|
---|
30 |
|
---|
31 | typedef struct
|
---|
32 | {
|
---|
33 | double value;
|
---|
34 | int ndigit;
|
---|
35 | int decpt;
|
---|
36 | char result[30];
|
---|
37 | } testcase;
|
---|
38 |
|
---|
39 | typedef char * ((*efcvt_func) (double, int, int *, int *));
|
---|
40 |
|
---|
41 | typedef int ((*efcvt_r_func) (double, int, int *, int *, char *, size_t));
|
---|
42 |
|
---|
43 |
|
---|
44 | static testcase ecvt_tests[] =
|
---|
45 | {
|
---|
46 | { 0.0, 0, 1, "" },
|
---|
47 | { 10.0, 0, 2, "" },
|
---|
48 | { 10.0, 1, 2, "1" },
|
---|
49 | { 10.0, 5, 2, "10000" },
|
---|
50 | { -12.0, 5, 2, "12000" },
|
---|
51 | { 0.2, 4, 0, "2000" },
|
---|
52 | { 0.02, 4, -1, "2000" },
|
---|
53 | { 5.5, 1, 1, "6" },
|
---|
54 | { 1.0, -1, 1, "" },
|
---|
55 | { 0.01, 2, -1, "10" },
|
---|
56 | { 100.0, -2, 3, "" },
|
---|
57 | { 100.0, -5, 3, "" },
|
---|
58 | { 100.0, -4, 3, "" },
|
---|
59 | { 100.01, -4, 3, "" },
|
---|
60 | { 123.01, -4, 3, "" },
|
---|
61 | { 126.71, -4, 3, "" },
|
---|
62 | { 0.0, 4, 1, "0000" },
|
---|
63 | #if DBL_MANT_DIG == 53
|
---|
64 | { 0x1p-1074, 3, -323, "494" },
|
---|
65 | { -0x1p-1074, 3, -323, "494" },
|
---|
66 | #endif
|
---|
67 | /* -1.0 is end marker. */
|
---|
68 | { -1.0, 0, 0, "" }
|
---|
69 | };
|
---|
70 |
|
---|
71 | static testcase fcvt_tests[] =
|
---|
72 | {
|
---|
73 | { 0.0, 0, 1, "0" },
|
---|
74 | { 10.0, 0, 2, "10" },
|
---|
75 | { 10.0, 1, 2, "100" },
|
---|
76 | { 10.0, 4, 2, "100000" },
|
---|
77 | { -12.0, 5, 2, "1200000" },
|
---|
78 | { 0.2, 4, 0, "2000" },
|
---|
79 | { 0.02, 4, -1, "200" },
|
---|
80 | { 5.5, 1, 1, "55" },
|
---|
81 | { 5.5, 0, 1, "6" },
|
---|
82 | { 0.01, 2, -1, "1" },
|
---|
83 | { 100.0, -2, 3, "100" },
|
---|
84 | { 100.0, -5, 3, "100" },
|
---|
85 | { 100.0, -4, 3, "100" },
|
---|
86 | { 100.01, -4, 3, "100" },
|
---|
87 | { 123.01, -4, 3, "100" },
|
---|
88 | { 126.71, -4, 3, "100" },
|
---|
89 | { 322.5, 16, 3, "3225000000000000000" },
|
---|
90 | /* -1.0 is end marker. */
|
---|
91 | { -1.0, 0, 0, "" }
|
---|
92 | };
|
---|
93 |
|
---|
94 | static void
|
---|
95 | output_error (const char *name, double value, int ndigit,
|
---|
96 | const char *exp_p, int exp_decpt, int exp_sign,
|
---|
97 | char *res_p, int res_decpt, int res_sign)
|
---|
98 | {
|
---|
99 | printf ("%s returned wrong result for value: %f, ndigits: %d\n",
|
---|
100 | name, value, ndigit);
|
---|
101 | printf ("Result was p: \"%s\", decpt: %d, sign: %d\n",
|
---|
102 | res_p, res_decpt, res_sign);
|
---|
103 | printf ("Should be p: \"%s\", decpt: %d, sign: %d\n",
|
---|
104 | exp_p, exp_decpt, exp_sign);
|
---|
105 | ++error_count;
|
---|
106 | }
|
---|
107 |
|
---|
108 |
|
---|
109 | static void
|
---|
110 | output_r_error (const char *name, double value, int ndigit,
|
---|
111 | const char *exp_p, int exp_decpt, int exp_sign, int exp_return,
|
---|
112 | char *res_p, int res_decpt, int res_sign, int res_return)
|
---|
113 | {
|
---|
114 | printf ("%s returned wrong result for value: %f, ndigits: %d\n",
|
---|
115 | name, value, ndigit);
|
---|
116 | printf ("Result was buf: \"%s\", decpt: %d, sign: %d return value: %d\n",
|
---|
117 | res_p, res_decpt, res_sign, res_return);
|
---|
118 | printf ("Should be buf: \"%s\", decpt: %d, sign: %d\n",
|
---|
119 | exp_p, exp_decpt, exp_sign);
|
---|
120 | ++error_count;
|
---|
121 | }
|
---|
122 |
|
---|
123 | static void
|
---|
124 | test (testcase tests[], efcvt_func efcvt, const char *name)
|
---|
125 | {
|
---|
126 | int no = 0;
|
---|
127 | int decpt, sign;
|
---|
128 | char *p;
|
---|
129 |
|
---|
130 | while (tests[no].value != -1.0)
|
---|
131 | {
|
---|
132 | p = efcvt (tests[no].value, tests[no].ndigit, &decpt, &sign);
|
---|
133 | if (decpt != tests[no].decpt
|
---|
134 | || sign != (tests[no].value < 0)
|
---|
135 | || strcmp (p, tests[no].result) != 0)
|
---|
136 | output_error (name, tests[no].value, tests[no].ndigit,
|
---|
137 | tests[no].result, tests[no].decpt,
|
---|
138 | (tests[no].value < 0),
|
---|
139 | p, decpt, sign);
|
---|
140 | ++no;
|
---|
141 | }
|
---|
142 | }
|
---|
143 |
|
---|
144 | static void
|
---|
145 | test_r (testcase tests[], efcvt_r_func efcvt_r, const char *name)
|
---|
146 | {
|
---|
147 | int no = 0;
|
---|
148 | int decpt, sign, res;
|
---|
149 | char buf [1024];
|
---|
150 |
|
---|
151 |
|
---|
152 | while (tests[no].value != -1.0)
|
---|
153 | {
|
---|
154 | res = efcvt_r (tests[no].value, tests[no].ndigit, &decpt, &sign,
|
---|
155 | buf, sizeof (buf));
|
---|
156 | if (res != 0
|
---|
157 | || decpt != tests[no].decpt
|
---|
158 | || sign != (tests[no].value < 0)
|
---|
159 | || strcmp (buf, tests[no].result) != 0)
|
---|
160 | output_r_error (name, tests[no].value, tests[no].ndigit,
|
---|
161 | tests[no].result, tests[no].decpt, 0,
|
---|
162 | (tests[no].value < 0),
|
---|
163 | buf, decpt, sign, res);
|
---|
164 | ++no;
|
---|
165 | }
|
---|
166 | }
|
---|
167 |
|
---|
168 | static void
|
---|
169 | special (void)
|
---|
170 | {
|
---|
171 | int decpt, sign, res;
|
---|
172 | char *p;
|
---|
173 | char buf [1024];
|
---|
174 |
|
---|
175 | p = ecvt (NAN, 10, &decpt, &sign);
|
---|
176 | if (sign != 0 || strcmp (p, "nan") != 0)
|
---|
177 | output_error ("ecvt", NAN, 10, "nan", 0, 0, p, decpt, sign);
|
---|
178 |
|
---|
179 | p = ecvt (INFINITY, 10, &decpt, &sign);
|
---|
180 | if (sign != 0 || strcmp (p, "inf") != 0)
|
---|
181 | output_error ("ecvt", NAN, 10, "inf", 0, 0, p, decpt, sign);
|
---|
182 |
|
---|
183 | /* Simply make sure these calls with large NDIGITs don't crash. */
|
---|
184 | (void) ecvt (123.456, 10000, &decpt, &sign);
|
---|
185 | (void) fcvt (123.456, 10000, &decpt, &sign);
|
---|
186 |
|
---|
187 | /* Some tests for for the reentrant functions. */
|
---|
188 | /* Use a too small buffer. */
|
---|
189 | res = ecvt_r (123.456, 10, &decpt, &sign, buf, 1);
|
---|
190 | if (res == 0)
|
---|
191 | {
|
---|
192 | printf ("ecvt_r with a too small buffer was succesful.\n");
|
---|
193 | ++error_count;
|
---|
194 | }
|
---|
195 | res = fcvt_r (123.456, 10, &decpt, &sign, buf, 1);
|
---|
196 | if (res == 0)
|
---|
197 | {
|
---|
198 | printf ("fcvt_r with a too small buffer was succesful.\n");
|
---|
199 | ++error_count;
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 | int
|
---|
205 | main (void)
|
---|
206 | {
|
---|
207 | test (ecvt_tests, ecvt, "ecvt");
|
---|
208 | test (fcvt_tests, fcvt, "fcvt");
|
---|
209 | test_r (ecvt_tests, ecvt_r, "ecvt_r");
|
---|
210 | test_r (fcvt_tests, fcvt_r, "fcvt_r");
|
---|
211 | special ();
|
---|
212 |
|
---|
213 | return error_count;
|
---|
214 | }
|
---|