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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c0c38c7c was c0c38c7c, checked in by Martin Decky <martin@…>, 10 years ago

software floating point overhaul
use proper type mapping
fix cosine calculation

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