2 * Copyright (c) 2012 Martin Decky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <mathtypes.h>
38 #include <comparison.h>
39 #include <conversion.h>
40 #include "../tester.h"
42 #define add_float __addsf3
43 #define sub_float __subsf3
44 #define mul_float __mulsf3
45 #define div_float __divsf3
47 #define is_float_lt __ltsf2
48 #define is_float_gt __gtsf2
49 #define is_float_eq __eqsf2
51 #define add_double __adddf3
52 #define sub_double __subdf3
53 #define mul_double __muldf3
54 #define div_double __divdf3
56 #define is_double_lt __ltdf2
57 #define is_double_gt __gtdf2
58 #define is_double_eq __eqdf2
60 #define uint_to_double __floatsidf
61 #define double_to_uint __fixunsdfsi
62 #define double_to_int __fixdfsi
65 #define PRECISION 1000
67 #define PRIdCMPTYPE PRId32
69 typedef int32_t cmptype_t
;
71 typedef void (* uint_to_double_op_t
)(unsigned int, double *, double *);
72 typedef void (* double_to_uint_op_t
)(double, unsigned int *, unsigned int *);
73 typedef void (* float_binary_op_t
)(float, float, float *, float *);
74 typedef void (* float_cmp_op_t
)(float, float, cmptype_t
*, cmptype_t
*);
75 typedef void (* double_binary_op_t
)(double, double, double *, double *);
76 typedef void (* double_cmp_op_t
)(double, double, cmptype_t
*, cmptype_t
*);
78 typedef void (* template_unary_t
)(void *, unsigned, cmptype_t
*, cmptype_t
*);
79 typedef void (* template_binary_t
)(void *, unsigned, unsigned, cmptype_t
*,
83 3.5, -2.1, 100.0, 50.0, -1024.0, 0.0, 768.3156, 1080.499999, -600.0, 1.0
85 static float fop_a
[OPERANDS
] = {
89 static double dop_a
[OPERANDS
] = {
93 static unsigned int uop_a
[OPERANDS
] = {
94 4, 2, 100, 50, 1024, 0, 1000000, 1, 0x8000000, 500
97 static int fcmp(float a
, float b
)
108 static int dcmp(double a
, double b
)
119 static void uint_to_double_template(void *f
, unsigned i
, cmptype_t
*pic
,
122 uint_to_double_op_t op
= (uint_to_double_op_t
) f
;
126 op(uop_a
[i
], &c
, &sc
);
128 *pic
= (cmptype_t
) (c
* PRECISION
);
129 *pisc
= (cmptype_t
) (sc
* PRECISION
);
132 static void double_to_uint_template(void *f
, unsigned i
, cmptype_t
*pic
,
135 double_to_uint_op_t op
= (double_to_uint_op_t
) f
;
139 op(dop_a
[i
], &c
, &sc
);
141 *pic
= (cmptype_t
) c
;
142 *pisc
= (cmptype_t
) sc
;
145 static void float_template_binary(void *f
, unsigned i
, unsigned j
,
146 cmptype_t
*pic
, cmptype_t
*pisc
)
148 float_binary_op_t op
= (float_binary_op_t
) f
;
152 op(fop_a
[i
], fop_a
[j
], &c
, &sc
);
154 *pic
= (cmptype_t
) (c
* PRECISION
);
155 *pisc
= (cmptype_t
) (sc
* PRECISION
);
158 static void float_compare_template(void *f
, unsigned i
, unsigned j
,
159 cmptype_t
*pis
, cmptype_t
*piss
)
161 float_cmp_op_t op
= (float_cmp_op_t
) f
;
163 op(dop_a
[i
], dop_a
[j
], pis
, piss
);
166 static void double_template_binary(void *f
, unsigned i
, unsigned j
,
167 cmptype_t
*pic
, cmptype_t
*pisc
)
169 double_binary_op_t op
= (double_binary_op_t
) f
;
173 op(dop_a
[i
], dop_a
[j
], &c
, &sc
);
175 *pic
= (cmptype_t
) (c
* PRECISION
);
176 *pisc
= (cmptype_t
) (sc
* PRECISION
);
179 static void double_compare_template(void *f
, unsigned i
, unsigned j
,
180 cmptype_t
*pis
, cmptype_t
*piss
)
182 double_cmp_op_t op
= (double_cmp_op_t
) f
;
184 op(dop_a
[i
], dop_a
[j
], pis
, piss
);
187 static bool test_template_unary(template_unary_t
template, void *f
)
191 for (unsigned int i
= 0; i
< OPERANDS
; i
++) {
195 template(f
, i
, &ic
, &isc
);
196 cmptype_t diff
= ic
- isc
;
199 TPRINTF("i=%u ic=%" PRIdCMPTYPE
" isc=%" PRIdCMPTYPE
"\n",
208 static bool test_template_binary(template_binary_t
template, void *f
)
212 for (unsigned int i
= 0; i
< OPERANDS
; i
++) {
213 for (unsigned int j
= 0; j
< OPERANDS
; j
++) {
217 template(f
, i
, j
, &ic
, &isc
);
218 cmptype_t diff
= ic
- isc
;
221 TPRINTF("i=%u, j=%u ic=%" PRIdCMPTYPE
222 " isc=%" PRIdCMPTYPE
"\n", i
, j
, ic
, isc
);
231 static void uint_to_double_operator(unsigned int a
, double *pc
, double *psc
)
234 *psc
= uint_to_double(a
);
237 static void double_to_uint_operator(double a
, unsigned int *pc
,
240 *pc
= (unsigned int) a
;
241 *psc
= double_to_uint(a
);
244 static void double_to_int_operator(double a
, unsigned int *pc
,
248 *psc
= double_to_int(a
);
251 static void float_add_operator(float a
, float b
, float *pc
, float *psc
)
254 *psc
= add_float(a
, b
);
257 static void float_sub_operator(float a
, float b
, float *pc
, float *psc
)
260 *psc
= sub_float(a
, b
);
263 static void float_mul_operator(float a
, float b
, float *pc
, float *psc
)
266 *psc
= mul_float(a
, b
);
269 static void float_div_operator(float a
, float b
, float *pc
, float *psc
)
271 if ((cmptype_t
) b
== 0) {
278 *psc
= div_float(a
, b
);
281 static void float_cmp_operator(float a
, float b
, cmptype_t
*pis
,
286 if (is_float_lt(a
, b
) == -1)
288 else if (is_float_gt(a
, b
) == 1)
290 else if (is_float_eq(a
, b
) == 0)
296 static void double_add_operator(double a
, double b
, double *pc
, double *psc
)
299 *psc
= add_double(a
, b
);
302 static void double_sub_operator(double a
, double b
, double *pc
, double *psc
)
305 *psc
= sub_double(a
, b
);
308 static void double_mul_operator(double a
, double b
, double *pc
, double *psc
)
311 *psc
= mul_double(a
, b
);
314 static void double_div_operator(double a
, double b
, double *pc
, double *psc
)
316 if ((cmptype_t
) b
== 0) {
323 *psc
= div_double(a
, b
);
326 static void double_cmp_operator(double a
, double b
, cmptype_t
*pis
,
331 if (is_double_lt(a
, b
) == -1)
333 else if (is_double_gt(a
, b
) == 1)
335 else if (is_double_eq(a
, b
) == 0)
341 const char *test_softfloat1(void)
345 if (!test_template_binary(float_template_binary
, float_add_operator
)) {
347 TPRINTF("%s\n", "Float addition failed");
350 if (!test_template_binary(float_template_binary
, float_sub_operator
)) {
352 TPRINTF("%s\n", "Float addition failed");
355 if (!test_template_binary(float_template_binary
, float_mul_operator
)) {
357 TPRINTF("%s\n", "Float multiplication failed");
360 if (!test_template_binary(float_template_binary
, float_div_operator
)) {
362 TPRINTF("%s\n", "Float division failed");
365 if (!test_template_binary(float_compare_template
, float_cmp_operator
)) {
367 TPRINTF("%s\n", "Float comparison failed");
370 if (!test_template_binary(double_template_binary
, double_add_operator
)) {
372 TPRINTF("%s\n", "Double addition failed");
375 if (!test_template_binary(double_template_binary
, double_sub_operator
)) {
377 TPRINTF("%s\n", "Double addition failed");
380 if (!test_template_binary(double_template_binary
, double_mul_operator
)) {
382 TPRINTF("%s\n", "Double multiplication failed");
385 if (!test_template_binary(double_template_binary
, double_div_operator
)) {
387 TPRINTF("%s\n", "Double division failed");
390 if (!test_template_binary(double_compare_template
, double_cmp_operator
)) {
392 TPRINTF("%s\n", "Double comparison failed");
395 if (!test_template_unary(uint_to_double_template
,
396 uint_to_double_operator
)) {
398 TPRINTF("%s\n", "Conversion from unsigned int to double failed");
401 if (!test_template_unary(double_to_uint_template
,
402 double_to_uint_operator
)) {
404 TPRINTF("%s\n", "Conversion from double to unsigned int failed");
407 if (!test_template_unary(double_to_uint_template
,
408 double_to_int_operator
)) {
410 TPRINTF("%s\n", "Conversion from double to signed int failed");
414 return "Software floating point imprecision";