source: mainline/uspace/app/tester/float/softfloat1.c@ 673ea28

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 673ea28 was 16bfcd3, checked in by jzr <zarevucky.jiri@…>, 8 years ago

Fix up headers.

  • Property mode set to 100644
File size: 9.7 KB
RevLine 
[b6636dc]1/*
2 * Copyright (c) 2012 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
[582a0b8]31#include <stdbool.h>
32#include <stddef.h>
[16bfcd3]33#include <inttypes.h>
[c0c38c7c]34#include <mathtypes.h>
[b6636dc]35#include <add.h>
[b60faf7]36#include <sub.h>
[e9d0ed4]37#include <mul.h>
38#include <div.h>
[c0f8909]39#include <comparison.h>
[a9f730a]40#include <conversion.h>
[b6636dc]41#include "../tester.h"
42
[c0c38c7c]43#define add_float __addsf3
44#define sub_float __subsf3
45#define mul_float __mulsf3
46#define div_float __divsf3
47
48#define is_float_lt __ltsf2
49#define is_float_gt __gtsf2
50#define is_float_eq __eqsf2
51
52#define add_double __adddf3
53#define sub_double __subdf3
54#define mul_double __muldf3
55#define div_double __divdf3
56
57#define is_double_lt __ltdf2
58#define is_double_gt __gtdf2
59#define is_double_eq __eqdf2
60
61#define uint_to_double __floatsidf
62#define double_to_uint __fixunsdfsi
63#define double_to_int __fixdfsi
64
[7218fe6]65#define OPERANDS 10
[c0c38c7c]66#define PRECISION 1000
[b6636dc]67
68#define PRIdCMPTYPE PRId32
69
70typedef int32_t cmptype_t;
[a9f730a]71
[c0c38c7c]72typedef void (* uint_to_double_op_t)(unsigned int, double *, double *);
[a9f730a]73typedef void (* double_to_uint_op_t)(double, unsigned int *, unsigned int *);
[c0c38c7c]74typedef void (* float_binary_op_t)(float, float, float *, float *);
75typedef void (* float_cmp_op_t)(float, float, cmptype_t *, cmptype_t *);
76typedef void (* double_binary_op_t)(double, double, double *, double *);
[c0f8909]77typedef void (* double_cmp_op_t)(double, double, cmptype_t *, cmptype_t *);
[a9f730a]78
79typedef void (* template_unary_t)(void *, unsigned, cmptype_t *, cmptype_t *);
[00e3ad2]80typedef void (* template_binary_t)(void *, unsigned, unsigned, cmptype_t *,
[000494d]81 cmptype_t *);
[b6636dc]82
[7218fe6]83#define NUMBERS \
[02ce8a0]84 3.5, -2.1, 100.0, 50.0, -1024.0, 0.0, 768.3156, 1080.499999, -600.0, 1.0
[b6636dc]85
[02ce8a0]86static float fop_a[OPERANDS] = {
87 NUMBERS
88};
[000494d]89
[7218fe6]90static double dop_a[OPERANDS] = {
[02ce8a0]91 NUMBERS
92};
[000494d]93
[02ce8a0]94static unsigned int uop_a[OPERANDS] = {
[c0c38c7c]95 4, 2, 100, 50, 1024, 0, 1000000, 1, 0x8000000, 500
[02ce8a0]96};
[a9f730a]97
[c0c38c7c]98static int fcmp(float a, float b)
[b6636dc]99{
[c0c38c7c]100 if (a < b)
101 return -1;
102
103 if (a > b)
104 return 1;
[b6636dc]105
[c0c38c7c]106 return 0;
[b6636dc]107}
108
[c0f8909]109static int dcmp(double a, double b)
110{
111 if (a < b)
112 return -1;
[7218fe6]113
114 if (a > b)
[c0f8909]115 return 1;
[7218fe6]116
[c0f8909]117 return 0;
118}
119
[7218fe6]120static void uint_to_double_template(void *f, unsigned i, cmptype_t *pic,
121 cmptype_t *pisc)
[a9f730a]122{
123 uint_to_double_op_t op = (uint_to_double_op_t) f;
124
[7218fe6]125 double c;
[c0c38c7c]126 double sc;
[a9f730a]127 op(uop_a[i], &c, &sc);
[7218fe6]128
[a9f730a]129 *pic = (cmptype_t) (c * PRECISION);
[c0c38c7c]130 *pisc = (cmptype_t) (sc * PRECISION);
[a9f730a]131}
132
[7218fe6]133static void double_to_uint_template(void *f, unsigned i, cmptype_t *pic,
134 cmptype_t *pisc)
[a9f730a]135{
136 double_to_uint_op_t op = (double_to_uint_op_t) f;
137
[7218fe6]138 unsigned int c;
139 unsigned int sc;
[a9f730a]140 op(dop_a[i], &c, &sc);
[7218fe6]141
[a9f730a]142 *pic = (cmptype_t) c;
143 *pisc = (cmptype_t) sc;
144}
145
[7218fe6]146static void float_template_binary(void *f, unsigned i, unsigned j,
147 cmptype_t *pic, cmptype_t *pisc)
[000494d]148{
[00e3ad2]149 float_binary_op_t op = (float_binary_op_t) f;
[000494d]150
[7218fe6]151 float c;
[c0c38c7c]152 float sc;
[02ce8a0]153 op(fop_a[i], fop_a[j], &c, &sc);
[7218fe6]154
[000494d]155 *pic = (cmptype_t) (c * PRECISION);
[c0c38c7c]156 *pisc = (cmptype_t) (sc * PRECISION);
157}
158
159static void float_compare_template(void *f, unsigned i, unsigned j,
160 cmptype_t *pis, cmptype_t *piss)
161{
162 float_cmp_op_t op = (float_cmp_op_t) f;
163
164 op(dop_a[i], dop_a[j], pis, piss);
[000494d]165}
166
[7218fe6]167static void double_template_binary(void *f, unsigned i, unsigned j,
168 cmptype_t *pic, cmptype_t *pisc)
[000494d]169{
[00e3ad2]170 double_binary_op_t op = (double_binary_op_t) f;
[000494d]171
[7218fe6]172 double c;
[c0c38c7c]173 double sc;
[02ce8a0]174 op(dop_a[i], dop_a[j], &c, &sc);
[7218fe6]175
[000494d]176 *pic = (cmptype_t) (c * PRECISION);
[c0c38c7c]177 *pisc = (cmptype_t) (sc * PRECISION);
[000494d]178}
179
[7218fe6]180static void double_compare_template(void *f, unsigned i, unsigned j,
181 cmptype_t *pis, cmptype_t *piss)
[c0f8909]182{
183 double_cmp_op_t op = (double_cmp_op_t) f;
184
[02ce8a0]185 op(dop_a[i], dop_a[j], pis, piss);
[c0f8909]186}
187
[a9f730a]188static bool test_template_unary(template_unary_t template, void *f)
189{
190 bool correct = true;
191
192 for (unsigned int i = 0; i < OPERANDS; i++) {
193 cmptype_t ic;
194 cmptype_t isc;
[7218fe6]195
196 template(f, i, &ic, &isc);
[c0c38c7c]197 cmptype_t diff = ic - isc;
[7218fe6]198
[a9f730a]199 if (diff != 0) {
[c0c38c7c]200 TPRINTF("i=%u ic=%" PRIdCMPTYPE " isc=%" PRIdCMPTYPE "\n",
201 i, ic, isc);
[a9f730a]202 correct = false;
203 }
204 }
205
206 return correct;
207}
208
[00e3ad2]209static bool test_template_binary(template_binary_t template, void *f)
[b6636dc]210{
211 bool correct = true;
212
213 for (unsigned int i = 0; i < OPERANDS; i++) {
[7218fe6]214 for (unsigned int j = 0; j < OPERANDS; j++) {
[000494d]215 cmptype_t ic;
216 cmptype_t isc;
[7218fe6]217
218 template(f, i, j, &ic, &isc);
[c0c38c7c]219 cmptype_t diff = ic - isc;
[b6636dc]220
221 if (diff != 0) {
[c0c38c7c]222 TPRINTF("i=%u, j=%u ic=%" PRIdCMPTYPE
223 " isc=%" PRIdCMPTYPE "\n", i, j, ic, isc);
[b6636dc]224 correct = false;
225 }
226 }
227 }
228
229 return correct;
230}
231
[c0c38c7c]232static void uint_to_double_operator(unsigned int a, double *pc, double *psc)
[a9f730a]233{
234 *pc = (double) a;
[c0c38c7c]235 *psc = uint_to_double(a);
[a9f730a]236}
237
[7218fe6]238static void double_to_uint_operator(double a, unsigned int *pc,
239 unsigned int *psc)
[a9f730a]240{
241 *pc = (unsigned int) a;
[c0c38c7c]242 *psc = double_to_uint(a);
[a9f730a]243}
244
[7218fe6]245static void double_to_int_operator(double a, unsigned int *pc,
246 unsigned int *psc)
[a9f730a]247{
248 *pc = (int) a;
[c0c38c7c]249 *psc = double_to_int(a);
[a9f730a]250}
251
[c0c38c7c]252static void float_add_operator(float a, float b, float *pc, float *psc)
[e9d0ed4]253{
[000494d]254 *pc = a + b;
[c0c38c7c]255 *psc = add_float(a, b);
[000494d]256}
257
[c0c38c7c]258static void float_sub_operator(float a, float b, float *pc, float *psc)
259{
260 *pc = a - b;
261 *psc = sub_float(a, b);
262}
263
264static void float_mul_operator(float a, float b, float *pc, float *psc)
[000494d]265{
266 *pc = a * b;
[c0c38c7c]267 *psc = mul_float(a, b);
[e9d0ed4]268}
269
[c0c38c7c]270static void float_div_operator(float a, float b, float *pc, float *psc)
[e9d0ed4]271{
[000494d]272 if ((cmptype_t) b == 0) {
273 *pc = 0.0;
[c0c38c7c]274 *psc = 0.0;
[000494d]275 return;
276 }
[7218fe6]277
[000494d]278 *pc = a / b;
[c0c38c7c]279 *psc = div_float(a, b);
280}
281
282static void float_cmp_operator(float a, float b, cmptype_t *pis,
283 cmptype_t *piss)
284{
285 *pis = fcmp(a, b);
[e9d0ed4]286
[c0c38c7c]287 if (is_float_lt(a, b) == -1)
288 *piss = -1;
289 else if (is_float_gt(a, b) == 1)
290 *piss = 1;
291 else if (is_float_eq(a, b) == 0)
292 *piss = 0;
293 else
294 *piss = 42;
[000494d]295}
[e9d0ed4]296
[c0c38c7c]297static void double_add_operator(double a, double b, double *pc, double *psc)
[000494d]298{
299 *pc = a + b;
[c0c38c7c]300 *psc = add_double(a, b);
301}
302
303static void double_sub_operator(double a, double b, double *pc, double *psc)
304{
305 *pc = a - b;
306 *psc = sub_double(a, b);
[000494d]307}
[e9d0ed4]308
[c0c38c7c]309static void double_mul_operator(double a, double b, double *pc, double *psc)
[000494d]310{
311 *pc = a * b;
[c0c38c7c]312 *psc = mul_double(a, b);
[000494d]313}
314
[c0c38c7c]315static void double_div_operator(double a, double b, double *pc, double *psc)
[000494d]316{
317 if ((cmptype_t) b == 0) {
318 *pc = 0.0;
[c0c38c7c]319 *psc = 0.0;
[000494d]320 return;
[e9d0ed4]321 }
[7218fe6]322
[000494d]323 *pc = a / b;
[c0c38c7c]324 *psc = div_double(a, b);
[e9d0ed4]325}
326
[7218fe6]327static void double_cmp_operator(double a, double b, cmptype_t *pis,
328 cmptype_t *piss)
[c0f8909]329{
330 *pis = dcmp(a, b);
[7218fe6]331
[c0c38c7c]332 if (is_double_lt(a, b) == -1)
[c0f8909]333 *piss = -1;
[c0c38c7c]334 else if (is_double_gt(a, b) == 1)
[c0f8909]335 *piss = 1;
[c0c38c7c]336 else if (is_double_eq(a, b) == 0)
[c0f8909]337 *piss = 0;
338 else
339 *piss = 42;
340}
341
[b6636dc]342const char *test_softfloat1(void)
343{
[c0c38c7c]344 bool err = false;
[7218fe6]345
[00e3ad2]346 if (!test_template_binary(float_template_binary, float_add_operator)) {
[c0c38c7c]347 err = true;
348 TPRINTF("%s\n", "Float addition failed");
349 }
350
351 if (!test_template_binary(float_template_binary, float_sub_operator)) {
352 err = true;
353 TPRINTF("%s\n", "Float addition failed");
[000494d]354 }
[7218fe6]355
[00e3ad2]356 if (!test_template_binary(float_template_binary, float_mul_operator)) {
[c0c38c7c]357 err = true;
358 TPRINTF("%s\n", "Float multiplication failed");
[000494d]359 }
[7218fe6]360
[00e3ad2]361 if (!test_template_binary(float_template_binary, float_div_operator)) {
[c0c38c7c]362 err = true;
363 TPRINTF("%s\n", "Float division failed");
364 }
365
366 if (!test_template_binary(float_compare_template, float_cmp_operator)) {
367 err = true;
368 TPRINTF("%s\n", "Float comparison failed");
[000494d]369 }
[7218fe6]370
[00e3ad2]371 if (!test_template_binary(double_template_binary, double_add_operator)) {
[c0c38c7c]372 err = true;
373 TPRINTF("%s\n", "Double addition failed");
374 }
375
376 if (!test_template_binary(double_template_binary, double_sub_operator)) {
377 err = true;
378 TPRINTF("%s\n", "Double addition failed");
[000494d]379 }
[7218fe6]380
[00e3ad2]381 if (!test_template_binary(double_template_binary, double_mul_operator)) {
[c0c38c7c]382 err = true;
383 TPRINTF("%s\n", "Double multiplication failed");
[000494d]384 }
[7218fe6]385
[00e3ad2]386 if (!test_template_binary(double_template_binary, double_div_operator)) {
[c0c38c7c]387 err = true;
388 TPRINTF("%s\n", "Double division failed");
[000494d]389 }
[7218fe6]390
[00e3ad2]391 if (!test_template_binary(double_compare_template, double_cmp_operator)) {
[c0c38c7c]392 err = true;
393 TPRINTF("%s\n", "Double comparison failed");
[c0f8909]394 }
[7218fe6]395
[a9f730a]396 if (!test_template_unary(uint_to_double_template,
397 uint_to_double_operator)) {
[c0c38c7c]398 err = true;
399 TPRINTF("%s\n", "Conversion from unsigned int to double failed");
[a9f730a]400 }
[7218fe6]401
[a9f730a]402 if (!test_template_unary(double_to_uint_template,
403 double_to_uint_operator)) {
[c0c38c7c]404 err = true;
405 TPRINTF("%s\n", "Conversion from double to unsigned int failed");
[a9f730a]406 }
[7218fe6]407
[a9f730a]408 if (!test_template_unary(double_to_uint_template,
409 double_to_int_operator)) {
[c0c38c7c]410 err = true;
411 TPRINTF("%s\n", "Conversion from double to signed int failed");
[a9f730a]412 }
[000494d]413
[c0c38c7c]414 if (err)
415 return "Software floating point imprecision";
416
417 return NULL;
[b6636dc]418}
Note: See TracBrowser for help on using the repository browser.