OSDN Git Service

e76cd512fc3a33fe5cf1a2949a4b5b512404390a
[mingw/mingw-org-wsl.git] / mingwrt / tests / powerfunc.at
1 # powerfunc.at
2 #
3 # Autotest module to verify correct operation of the pow(), powf(),
4 # and powl() functions; inspired by MinGW-Bug [#2306], and implemented
5 # to evaluate each boundary condition specified by POSIX.1-2008.
6 #
7 # $Id$
8 #
9 # Written by Keith Marshall <keithmarshall@users.sourceforge.net>
10 # Copyright (C) 2016, MinGW.org Project
11 #
12 #
13 # Permission is hereby granted, free of charge, to any person obtaining a
14 # copy of this software and associated documentation files (the "Software"),
15 # to deal in the Software without restriction, including without limitation
16 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 # and/or sell copies of the Software, and to permit persons to whom the
18 # Software is furnished to do so, subject to the following conditions:
19 #
20 # The above copyright notice and this permission notice (including the next
21 # paragraph) shall be included in all copies or substantial portions of the
22 # Software.
23 #
24 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 # AUTHORS OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 # DEALINGS IN THE SOFTWARE.
31 #
32 #
33 # All tests specified herein are written in the C language.
34 #
35 MINGW_AT_LANG([C])
36
37 # MINGW_AT_CHECK_RUN_POW( FUNCTION, X, Y, EXPOUT )
38 # ------------------------------------------------
39 # Set up the test case to evaluate FUNCTION, (one of pow, powf,
40 # or powl), with X and Y as arguments; confirm the the resultant
41 # output matches EXPOUT.
42 #
43 # Note: the M4 macros pow_datatype, pow_strtod, and pow_format
44 # MUST have been defined, before this macro is expanded.
45 #
46 m4_define([MINGW_AT_CHECK_RUN_POW],[
47 AT_SETUP([$1 (x = $2, y = $3)])
48 AT_KEYWORDS([C $1])MINGW_AT_DATA_CRLF([expout],[[$4
49 ]])MINGW_AT_CHECK_RUN([[[
50 #define _XOPEN_SOURCE 700
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <tgmath.h>
55 #include <errno.h>
56
57 #define EOK  0
58
59 const char *errdesc( void )
60 { /* A minimal replacement for strerror(), so we keep strict
61    * control of the descriptions for those errors which any of
62    * the pow() functions may report.
63    */
64   static char desc[8] = "";
65   switch( errno )
66   { case EOK:    return "ok";
67     case EDOM:   return "domain error";
68     case ERANGE: return "range error";
69     default: snprintf( desc, sizeof( desc ), "%d", errno );
70   }
71   return desc;
72 }
73
74 int main()
75 { /* Convert the specified X and Y arguments to the appropriate
76    * data type, invoke the specified FUNCTION, report its result,
77    * and any error which may have occurred.
78    */
79   ]]pow_datatype[[ result, x = ]]pow_strtod($2)[[, y = ]]pow_strtod($3)[[;
80   errno = EOK; result = $1(x, y); printf("]]pow_format[[", result, errdesc());
81   return EOK;
82 }]]],,[expout])dnl
83 AT_CLEANUP
84 ])
85
86 # MINGW_AT_CHECK_POW_FUNCTION( NAME )
87 # -----------------------------------
88 # Check the behaviour of function NAME, (one of pow, powf, or powl),
89 # for a selection of values of X and Y; further comments, embedded
90 # within this macro, specify POSIX.1-2008 mandatory outcomes.
91 #
92 m4_define([MINGW_AT_CHECK_POW_FUNCTION],[dnl
93 AT_BANNER([Power function tests: ]pow_datatype[ data.])
94 #
95 # On successful completion, return x to the power y
96 #
97 MINGW_AT_CHECK_RUN_POW([$1],[+2.0],[+2.5e+0],[+5.656854e+000 (ok)])
98 MINGW_AT_CHECK_RUN_POW([$1],[+1.2],[+2.5e+0],[+1.577441e+000 (ok)])
99 MINGW_AT_CHECK_RUN_POW([$1],[+0.3],[+2.5e+0],[+4.929503e-002 (ok)])
100 #
101 # For finite x < 0, and finite non-integral y, report "domain error",
102 # and return "NaN"; (note that MinGW's printf(), as used to report the
103 # result, always treats NaN as being unsigned, so we will always see
104 # it reported as "+nan", irrespective of sign bit).
105 #
106 MINGW_AT_CHECK_RUN_POW([$1],[-2.0],[+2.5e+0],[+nan (domain error)])
107 MINGW_AT_CHECK_RUN_POW([$1],[-2.0],[-2.5e+0],[+nan (domain error)])
108 #
109 # For finite x < 0, and finite integral y, no "domain error" arises;
110 # the result is analytically computable as -1.0^y * 2^(y*log2(|x|)).
111 #
112 MINGW_AT_CHECK_RUN_POW([$1],[-2.5],[+2.0e+0],[+6.250000e+000 (ok)])
113 MINGW_AT_CHECK_RUN_POW([$1],[-2.5],[+3.0e+0],[-1.562500e+001 (ok)])
114 MINGW_AT_CHECK_RUN_POW([$1],[-1.5],[-2.0e+0],[+4.444444e-001 (ok)])
115 MINGW_AT_CHECK_RUN_POW([$1],[-1.5],[-3.0e+0],[-2.962963e-001 (ok)])
116 #
117 # For non-zero result with no representation which is distinguishable
118 # from zero, (i.e. underflow), report "range error" and return zero.
119 #
120 MINGW_AT_CHECK_RUN_POW([$1],[+0.2],[+2.5e+4],[+0.000000e+000 (range error)])
121 #
122 # When |x| == 0, and y < 0, report "range error", (indicating a pole
123 # error), and return infinity with the sign of x if y is an odd valued
124 # -ve integer value, or +ve infinity for any other -ve value of y.
125 #
126 MINGW_AT_CHECK_RUN_POW([$1],[+0.0],[-1.0e+0],[+inf (range error)])
127 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[-1.0e+0],[-inf (range error)])
128 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[-7.0e+0],[-inf (range error)])
129 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[-2.0e+0],[+inf (range error)])
130 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[-1.1e+0],[+inf (range error)])
131 #
132 # When x == +1.0, for any value of y (including NaN), return +1.0
133 #
134 MINGW_AT_CHECK_RUN_POW([$1],[+1.0],[+2.5e+4],[+1.000000e+000 (ok)])
135 MINGW_AT_CHECK_RUN_POW([$1],[+1.0],[+Inf],   [+1.000000e+000 (ok)])
136 MINGW_AT_CHECK_RUN_POW([$1],[+1.0],[+NaN],   [+1.000000e+000 (ok)])
137 #
138 # for any value of x, (including infinity or NaN), when |y| is zero,
139 # return +1.0
140 #
141 MINGW_AT_CHECK_RUN_POW([$1],[+2.5],[+0.0e+0],[+1.000000e+000 (ok)])
142 MINGW_AT_CHECK_RUN_POW([$1],[-2.5],[-0.0e+0],[+1.000000e+000 (ok)])
143 MINGW_AT_CHECK_RUN_POW([$1],[+Inf],[+0.0e+0],[+1.000000e+000 (ok)])
144 MINGW_AT_CHECK_RUN_POW([$1],[+Inf],[-0.0e+0],[+1.000000e+000 (ok)])
145 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[+0.0e+0],[+1.000000e+000 (ok)])
146 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[-0.0e+0],[+1.000000e+000 (ok)])
147 MINGW_AT_CHECK_RUN_POW([$1],[+NaN],[+0.0e+0],[+1.000000e+000 (ok)])
148 MINGW_AT_CHECK_RUN_POW([$1],[+NaN],[-0.0e+0],[+1.000000e+000 (ok)])
149 #
150 # Other than the preceding special cases, if either x or y is NaN,
151 # return "NaN"; (POSIX specifies NO errno assignment).
152 #
153 MINGW_AT_CHECK_RUN_POW([$1],[+NaN],[+2.5e+0],[+nan (ok)])
154 MINGW_AT_CHECK_RUN_POW([$1],[-NaN],[+2.5e+0],[+nan (ok)])
155 MINGW_AT_CHECK_RUN_POW([$1],[+2.5],[-NaN],   [+nan (ok)])
156 MINGW_AT_CHECK_RUN_POW([$1],[-2.5],[+NaN],   [+nan (ok)])
157 #
158 # For any odd integer value of y > 0, if |x| == 0, return signed
159 # zero, with same sign as x, (i.e. value of x itself).
160 #
161 MINGW_AT_CHECK_RUN_POW([$1],[+0.0],[+3.0e+0],[+0.000000e+000 (ok)])
162 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[+3.0e+0],[-0.000000e+000 (ok)])
163 MINGW_AT_CHECK_RUN_POW([$1],[+0.0],[+7.0e+0],[+0.000000e+000 (ok)])
164 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[+7.0e+0],[-0.000000e+000 (ok)])
165 #
166 # For any other y > 0, (i.e. +ve but not an odd integer), if |x| == 0,
167 # return +0.0
168 #
169 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[+2.5e+0],[+0.000000e+000 (ok)])
170 MINGW_AT_CHECK_RUN_POW([$1],[-0.0],[+3.5e+4],[+0.000000e+000 (ok)])
171 #
172 # If x == -1, and y is +ve or -ve infinity, return +1.0
173 #
174 MINGW_AT_CHECK_RUN_POW([$1],[-1.0],[+Inf],   [+1.000000e+000 (ok)])
175 MINGW_AT_CHECK_RUN_POW([$1],[-1.0],[-Inf],   [+1.000000e+000 (ok)])
176 #
177 # When |x| < 1, and y is infinite, return +ve infinity when y is -ve
178 # infinity, or +0.0 when y is +ve infinity.
179 #
180 MINGW_AT_CHECK_RUN_POW([$1],[-0.3],[-Inf],   [+inf (ok)])
181 MINGW_AT_CHECK_RUN_POW([$1],[+0.7],[-Inf],   [+inf (ok)])
182 MINGW_AT_CHECK_RUN_POW([$1],[+0.3],[+Inf],   [+0.000000e+000 (ok)])
183 MINGW_AT_CHECK_RUN_POW([$1],[-0.7],[+Inf],   [+0.000000e+000 (ok)])
184 #
185 # When |x| > 1, and y is infinite, return +0.0 when y is -ve infinity,
186 # or +ve infinity when y is +ve infinity.
187 #
188 MINGW_AT_CHECK_RUN_POW([$1],[+5.3],[-Inf],   [+0.000000e+000 (ok)])
189 MINGW_AT_CHECK_RUN_POW([$1],[-1.7],[-Inf],   [+0.000000e+000 (ok)])
190 MINGW_AT_CHECK_RUN_POW([$1],[-5.3],[+Inf],   [+inf (ok)])
191 MINGW_AT_CHECK_RUN_POW([$1],[+1.7],[+Inf],   [+inf (ok)])
192 #
193 # If x is -ve infinity, and y < 0, return -ve zero if y is an odd
194 # valued -ve integer, otherwise return +ve zero.
195 #
196 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[-3.0e+0],[-0.000000e+000 (ok)])
197 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[-2.0e+0],[+0.000000e+000 (ok)])
198 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[-3.5e+0],[+0.000000e+000 (ok)])
199 #
200 # If x is -ve infinity, and y > 0, return -ve infinity if y is an odd
201 # valued +ve integer, otherwise return +ve infinity.
202 #
203 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[+3.0e+0],[-inf (ok)])
204 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[+2.0e+0],[+inf (ok)])
205 MINGW_AT_CHECK_RUN_POW([$1],[-Inf],[+3.5e+0],[+inf (ok)])
206 #
207 # If x is +ve infinity, and y < 0, return +ve zero.
208 #
209 MINGW_AT_CHECK_RUN_POW([$1],[+Inf],[-1.0e-4],[+0.000000e+000 (ok)])
210 MINGW_AT_CHECK_RUN_POW([$1],[+Inf],[-2.5e+4],[+0.000000e+000 (ok)])
211 #
212 # If x is +ve infinity, and y > 0, return +ve infinity.
213 #
214 MINGW_AT_CHECK_RUN_POW([$1],[+Inf],[+1.0e-4],[+inf (ok)])
215 MINGW_AT_CHECK_RUN_POW([$1],[+Inf],[+2.5e+4],[+inf (ok)])
216 #
217 # For result of magnitude greater than largest representable value,
218 # (i.e. overflow), report "range error", and return infinity; (this
219 # occurs at progressively lesser result boundaries, as we choose to
220 # evaluate with decreasing precision, i.e. using powl(), pow(), or
221 # powf(), respectively.  Only the first in this progression should
222 # pass without overflow in all three cases; the last will overflow
223 # in all cases, but to keep it in order, we must define it after
224 # each of those which behave differently in each case).
225 #
226 MINGW_AT_CHECK_RUN_POW([$1],[+2.0],[+2.5e+1],[+3.355443e+007 (ok)])
227 ])
228
229 # Set up the test sequence for the pow() function.
230 #
231 m4_define([pow_datatype],[double])
232 m4_define([pow_strtod],[[strtod("$1",NULL)]])
233 m4_define([pow_format],[[%+.6e (%s)\n]])
234 #
235 MINGW_AT_CHECK_POW_FUNCTION([pow])
236 #
237 # Add the three variants on the final progression, the first two of
238 # which differ in each specific pow(), powf(), and powl() case, and
239 # the final one, which is consistent, but we wish to keep it last.
240 #
241 MINGW_AT_CHECK_RUN_POW([pow],[+2.0],[+2.5e+2],[+1.809251e+075 (ok)])
242 MINGW_AT_CHECK_RUN_POW([pow],[+2.0],[+2.5e+3],[+inf (range error)])
243 MINGW_AT_CHECK_RUN_POW([pow],[+2.0],[+2.5e+4],[+inf (range error)])
244
245 # Repeat for the powf() function.
246 #
247 m4_define([pow_datatype],[float])
248 m4_define([pow_strtod],[[strtof("$1",NULL)]])
249 m4_define([pow_format],[[%+.6e (%s)\n]])
250 #
251 MINGW_AT_CHECK_POW_FUNCTION([powf])
252 #
253 # Once again, complete the progression of the final test case.
254 #
255 MINGW_AT_CHECK_RUN_POW([powf],[+2.0],[+2.5e+2],[+inf (range error)])
256 MINGW_AT_CHECK_RUN_POW([powf],[+2.0],[+2.5e+3],[+inf (range error)])
257 MINGW_AT_CHECK_RUN_POW([powf],[+2.0],[+2.5e+4],[+inf (range error)])
258
259 # And finally, for the powl() function.
260 #
261 m4_define([pow_datatype],[long double])
262 m4_define([pow_strtod],[[strtold("$1",NULL)]])
263 m4_define([pow_format],[[%+.6Le (%s)\n]])
264 #
265 MINGW_AT_CHECK_POW_FUNCTION([powl])
266 #
267 # Once again, complete the progression of the final test case.
268 #
269 MINGW_AT_CHECK_RUN_POW([powl],[+2.0],[+2.5e+2],[+1.809251e+075 (ok)])
270 MINGW_AT_CHECK_RUN_POW([powl],[+2.0],[+2.5e+3],[+3.758280e+752 (ok)])
271 MINGW_AT_CHECK_RUN_POW([powl],[+2.0],[+2.5e+4],[+inf (range error)])
272
273 # vim: filetype=config formatoptions=croql
274 # $RCSfile$: end of file