1 /* Copyright (C) 1998-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
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
23 FLOAT: The floating-point type, i.e. double or long double.
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.
30 PRINTF_CONVERSION: The appropriate printf conversion specifier with
31 length modifier for FLOAT, i.e. "%f" or "%Lf".
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. */
38 # define _GNU_SOURCE 1
46 #include <support/check.h>
48 #define NAME(x) NAMEX(x)
59 typedef char * ((*efcvt_func
) (FLOAT
, int, int *, int *));
61 typedef int ((*efcvt_r_func
) (FLOAT
, int, int *, int *, char *, size_t));
64 static testcase ecvt_tests
[] =
69 { 10.0, 5, 2, "10000" },
70 { -12.0, 5, 2, "12000" },
71 { 0.2, 4, 0, "2000" },
72 { 0.02, 4, -1, "2000" },
75 { 0.01, 2, -1, "10" },
79 { 100.01, -4, 3, "" },
80 { 123.01, -4, 3, "" },
81 { 126.71, -4, 3, "" },
82 { 0.0, 4, 1, "0000" },
84 /* -1.0 is end marker. */
88 static testcase fcvt_tests
[] =
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" },
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" },
106 { 322.5, 16, 3, "3225000000000000000" },
107 /* -1.0 is end marker. */
112 output_error (const char *name
, FLOAT value
, int ndigit
,
113 const char *exp_p
, int exp_decpt
, int exp_sign
,
114 char *res_p
, int res_decpt
, int res_sign
)
116 printf ("%s returned wrong result for value: " PRINTF_CONVERSION
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
);
123 support_record_failure ();
128 output_r_error (const char *name
, FLOAT value
, int ndigit
,
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
)
132 printf ("%s returned wrong result for value: " PRINTF_CONVERSION
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",
138 exp_p
, exp_decpt
, exp_sign
);
139 support_record_failure ();
143 test (testcase tests
[], efcvt_func efcvt
, const char *name
)
149 while (tests
[no
].value
!= -1.0)
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),
164 test_r (testcase tests
[], efcvt_r_func efcvt_r
, const char *name
)
167 int decpt
, sign
, res
;
171 while (tests
[no
].value
!= -1.0)
173 res
= efcvt_r (tests
[no
].value
, tests
[no
].ndigit
, &decpt
, &sign
,
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
);
190 int decpt
, sign
, res
;
194 p
= ECVT (NAN
, 10, &decpt
, &sign
);
195 if (sign
!= 0 || strcmp (p
, "nan") != 0)
196 output_error (NAME (ECVT
), NAN
, 10, "nan", 0, 0, p
, decpt
, sign
);
198 p
= ECVT (INFINITY
, 10, &decpt
, &sign
);
199 if (sign
!= 0 || strcmp (p
, "inf") != 0)
200 output_error (NAME (ECVT
), INFINITY
, 10, "inf", 0, 0, p
, decpt
, sign
);
202 /* Simply make sure these calls with large NDIGITs don't crash. */
203 p
= ECVT (123.456, 10000, &decpt
, &sign
);
204 p
= FCVT (123.456, 10000, &decpt
, &sign
);
206 /* Some tests for the reentrant functions. */
207 /* Use a too small buffer. */
208 res
= ECVT_R (123.456, 10, &decpt
, &sign
, buf
, 1);
211 printf (NAME (ECVT_R
) " with a too small buffer was successful.\n");
212 support_record_failure ();
214 res
= FCVT_R (123.456, 10, &decpt
, &sign
, buf
, 1);
217 printf (NAME (FCVT_R
) " with a too small buffer was successful.\n");
218 support_record_failure ();
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
));
235 #include <support/test-driver.c>