]>
Commit | Line | Data |
---|---|---|
2b778ceb | 1 | /* Copyright (C) 1998-2021 Free Software Foundation, Inc. |
07b51ba5 UD |
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 | |
41bdb6e2 AJ |
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. | |
07b51ba5 UD |
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 | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
07b51ba5 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
07b51ba5 | 17 | |
bd51ff5e GG |
18 | /* This template provides testing for the *cvt family of functions, |
19 | which deal with double or long double types. In order to use the | |
20 | template, the following macros must be defined before inclusion of | |
21 | this template: | |
22 | ||
23 | FLOAT: The floating-point type, i.e. double or long double. | |
24 | ||
25 | ECVT: Appropriate *ecvt function for FLOAT, i.e. ecvt or qecvt. | |
26 | FCVT: Likewise for *fcvt, i.e. fcvt or qfcvt. | |
27 | ECVT_R: Likewise for *ecvt_r, i.e. ecvt_r or qecvt_r. | |
28 | FCVT_R: Likewise for *fcvt_r, i.e. fcvt_r or qfcvt_r. | |
29 | ||
30 | PRINTF_CONVERSION: The appropriate printf conversion specifier with | |
31 | length modifier for FLOAT, i.e. "%f" or "%Lf". | |
32 | ||
33 | EXTRA_ECVT_TESTS: Additional tests for the ecvt or qecvt function | |
34 | that are only relevant to a particular floating-point type and | |
35 | cannot be represented generically. */ | |
36 | ||
da2d1bc5 UD |
37 | #ifndef _GNU_SOURCE |
38 | # define _GNU_SOURCE 1 | |
39 | #endif | |
40 | ||
41 | #include <math.h> | |
07b51ba5 UD |
42 | #include <stdio.h> |
43 | #include <stdlib.h> | |
3e1f480e | 44 | #include <string.h> |
07b51ba5 | 45 | |
968ed530 | 46 | #include <support/check.h> |
da2d1bc5 | 47 | |
bd51ff5e GG |
48 | #define NAME(x) NAMEX(x) |
49 | #define NAMEX(x) #x | |
50 | ||
a7f804d8 | 51 | typedef struct |
da2d1bc5 | 52 | { |
bd51ff5e | 53 | FLOAT value; |
da2d1bc5 UD |
54 | int ndigit; |
55 | int decpt; | |
56 | char result[30]; | |
57 | } testcase; | |
58 | ||
bd51ff5e | 59 | typedef char * ((*efcvt_func) (FLOAT, int, int *, int *)); |
da2d1bc5 | 60 | |
bd51ff5e | 61 | typedef int ((*efcvt_r_func) (FLOAT, int, int *, int *, char *, size_t)); |
c9e17a9c | 62 | |
da2d1bc5 UD |
63 | |
64 | static testcase ecvt_tests[] = | |
65 | { | |
66 | { 0.0, 0, 1, "" }, | |
67 | { 10.0, 0, 2, "" }, | |
68 | { 10.0, 1, 2, "1" }, | |
69 | { 10.0, 5, 2, "10000" }, | |
70 | { -12.0, 5, 2, "12000" }, | |
71 | { 0.2, 4, 0, "2000" }, | |
72 | { 0.02, 4, -1, "2000" }, | |
73 | { 5.5, 1, 1, "6" }, | |
74 | { 1.0, -1, 1, "" }, | |
75 | { 0.01, 2, -1, "10" }, | |
1eb687d0 UD |
76 | { 100.0, -2, 3, "" }, |
77 | { 100.0, -5, 3, "" }, | |
78 | { 100.0, -4, 3, "" }, | |
79 | { 100.01, -4, 3, "" }, | |
80 | { 123.01, -4, 3, "" }, | |
81 | { 126.71, -4, 3, "" }, | |
a7f804d8 | 82 | { 0.0, 4, 1, "0000" }, |
bd51ff5e | 83 | EXTRA_ECVT_TESTS |
da2d1bc5 UD |
84 | /* -1.0 is end marker. */ |
85 | { -1.0, 0, 0, "" } | |
86 | }; | |
87 | ||
88 | static testcase fcvt_tests[] = | |
89 | { | |
90 | { 0.0, 0, 1, "0" }, | |
91 | { 10.0, 0, 2, "10" }, | |
92 | { 10.0, 1, 2, "100" }, | |
93 | { 10.0, 4, 2, "100000" }, | |
94 | { -12.0, 5, 2, "1200000" }, | |
95 | { 0.2, 4, 0, "2000" }, | |
96 | { 0.02, 4, -1, "200" }, | |
97 | { 5.5, 1, 1, "55" }, | |
98 | { 5.5, 0, 1, "6" }, | |
99 | { 0.01, 2, -1, "1" }, | |
1eb687d0 UD |
100 | { 100.0, -2, 3, "100" }, |
101 | { 100.0, -5, 3, "100" }, | |
102 | { 100.0, -4, 3, "100" }, | |
103 | { 100.01, -4, 3, "100" }, | |
104 | { 123.01, -4, 3, "100" }, | |
105 | { 126.71, -4, 3, "100" }, | |
887e7ab6 | 106 | { 322.5, 16, 3, "3225000000000000000" }, |
da2d1bc5 UD |
107 | /* -1.0 is end marker. */ |
108 | { -1.0, 0, 0, "" } | |
109 | }; | |
110 | ||
de149cdb | 111 | static void |
bd51ff5e | 112 | output_error (const char *name, FLOAT value, int ndigit, |
da2d1bc5 UD |
113 | const char *exp_p, int exp_decpt, int exp_sign, |
114 | char *res_p, int res_decpt, int res_sign) | |
115 | { | |
bd51ff5e GG |
116 | printf ("%s returned wrong result for value: " PRINTF_CONVERSION |
117 | ", ndigits: %d\n", | |
da2d1bc5 UD |
118 | name, value, ndigit); |
119 | printf ("Result was p: \"%s\", decpt: %d, sign: %d\n", | |
120 | res_p, res_decpt, res_sign); | |
121 | printf ("Should be p: \"%s\", decpt: %d, sign: %d\n", | |
122 | exp_p, exp_decpt, exp_sign); | |
968ed530 | 123 | support_record_failure (); |
da2d1bc5 UD |
124 | } |
125 | ||
c9e17a9c | 126 | |
de149cdb | 127 | static void |
bd51ff5e | 128 | output_r_error (const char *name, FLOAT value, int ndigit, |
c9e17a9c UD |
129 | const char *exp_p, int exp_decpt, int exp_sign, int exp_return, |
130 | char *res_p, int res_decpt, int res_sign, int res_return) | |
131 | { | |
bd51ff5e GG |
132 | printf ("%s returned wrong result for value: " PRINTF_CONVERSION |
133 | ", ndigits: %d\n", | |
c9e17a9c UD |
134 | name, value, ndigit); |
135 | printf ("Result was buf: \"%s\", decpt: %d, sign: %d return value: %d\n", | |
136 | res_p, res_decpt, res_sign, res_return); | |
137 | printf ("Should be buf: \"%s\", decpt: %d, sign: %d\n", | |
1fc6f813 | 138 | exp_p, exp_decpt, exp_sign); |
968ed530 | 139 | support_record_failure (); |
c9e17a9c UD |
140 | } |
141 | ||
de149cdb | 142 | static void |
da2d1bc5 UD |
143 | test (testcase tests[], efcvt_func efcvt, const char *name) |
144 | { | |
145 | int no = 0; | |
146 | int decpt, sign; | |
147 | char *p; | |
148 | ||
149 | while (tests[no].value != -1.0) | |
150 | { | |
151 | p = efcvt (tests[no].value, tests[no].ndigit, &decpt, &sign); | |
152 | if (decpt != tests[no].decpt | |
153 | || sign != (tests[no].value < 0) | |
154 | || strcmp (p, tests[no].result) != 0) | |
155 | output_error (name, tests[no].value, tests[no].ndigit, | |
156 | tests[no].result, tests[no].decpt, | |
157 | (tests[no].value < 0), | |
158 | p, decpt, sign); | |
159 | ++no; | |
160 | } | |
161 | } | |
162 | ||
de149cdb | 163 | static void |
c9e17a9c UD |
164 | test_r (testcase tests[], efcvt_r_func efcvt_r, const char *name) |
165 | { | |
166 | int no = 0; | |
167 | int decpt, sign, res; | |
168 | char buf [1024]; | |
1fc6f813 | 169 | |
c9e17a9c UD |
170 | |
171 | while (tests[no].value != -1.0) | |
172 | { | |
173 | res = efcvt_r (tests[no].value, tests[no].ndigit, &decpt, &sign, | |
174 | buf, sizeof (buf)); | |
175 | if (res != 0 | |
176 | || decpt != tests[no].decpt | |
177 | || sign != (tests[no].value < 0) | |
178 | || strcmp (buf, tests[no].result) != 0) | |
179 | output_r_error (name, tests[no].value, tests[no].ndigit, | |
180 | tests[no].result, tests[no].decpt, 0, | |
181 | (tests[no].value < 0), | |
182 | buf, decpt, sign, res); | |
183 | ++no; | |
184 | } | |
185 | } | |
186 | ||
de149cdb | 187 | static void |
da2d1bc5 | 188 | special (void) |
07b51ba5 | 189 | { |
b9d3d9f7 | 190 | int decpt, sign, res; |
07b51ba5 | 191 | char *p; |
b9d3d9f7 | 192 | char buf [1024]; |
1fc6f813 | 193 | |
bd51ff5e | 194 | p = ECVT (NAN, 10, &decpt, &sign); |
da2d1bc5 | 195 | if (sign != 0 || strcmp (p, "nan") != 0) |
bd51ff5e | 196 | output_error (NAME (ECVT), NAN, 10, "nan", 0, 0, p, decpt, sign); |
07b51ba5 | 197 | |
bd51ff5e | 198 | p = ECVT (INFINITY, 10, &decpt, &sign); |
da2d1bc5 | 199 | if (sign != 0 || strcmp (p, "inf") != 0) |
bd51ff5e | 200 | output_error (NAME (ECVT), INFINITY, 10, "inf", 0, 0, p, decpt, sign); |
da2d1bc5 | 201 | |
67994d6f | 202 | /* Simply make sure these calls with large NDIGITs don't crash. */ |
bd51ff5e GG |
203 | (void) ECVT (123.456, 10000, &decpt, &sign); |
204 | (void) FCVT (123.456, 10000, &decpt, &sign); | |
67994d6f | 205 | |
ded5b9b7 | 206 | /* Some tests for the reentrant functions. */ |
b9d3d9f7 | 207 | /* Use a too small buffer. */ |
bd51ff5e | 208 | res = ECVT_R (123.456, 10, &decpt, &sign, buf, 1); |
b9d3d9f7 UD |
209 | if (res == 0) |
210 | { | |
bd51ff5e | 211 | printf (NAME (ECVT_R) " with a too small buffer was succesful.\n"); |
968ed530 | 212 | support_record_failure (); |
b9d3d9f7 | 213 | } |
bd51ff5e | 214 | res = FCVT_R (123.456, 10, &decpt, &sign, buf, 1); |
b9d3d9f7 UD |
215 | if (res == 0) |
216 | { | |
bd51ff5e | 217 | printf (NAME (FCVT_R) " with a too small buffer was succesful.\n"); |
968ed530 | 218 | support_record_failure (); |
b9d3d9f7 | 219 | } |
da2d1bc5 UD |
220 | } |
221 | ||
a7f804d8 | 222 | |
29955b5d AS |
223 | static int |
224 | do_test (void) | |
da2d1bc5 | 225 | { |
bd51ff5e GG |
226 | test (ecvt_tests, ECVT, NAME (ECVT)); |
227 | test (fcvt_tests, FCVT, NAME (FCVT)); | |
228 | test_r (ecvt_tests, ECVT_R, NAME (ECVT_R)); | |
229 | test_r (fcvt_tests, FCVT_R, NAME (FCVT_R)); | |
da2d1bc5 | 230 | special (); |
a7f804d8 | 231 | |
968ed530 | 232 | return 0; |
07b51ba5 | 233 | } |
29955b5d | 234 | |
968ed530 | 235 | #include <support/test-driver.c> |