Home | History | Annotate | Line # | Download | only in libm
t_fe_round.c revision 1.4
      1  1.1  maya /*
      2  1.1  maya  * Written by Maya Rashish <maya (at) NetBSD.org>
      3  1.1  maya  * Public domain.
      4  1.1  maya  *
      5  1.1  maya  * Testing IEEE-754 rounding modes (and lrint)
      6  1.1  maya  */
      7  1.1  maya 
      8  1.1  maya #include <atf-c.h>
      9  1.1  maya #include <fenv.h>
     10  1.1  maya #ifdef __HAVE_FENV
     11  1.1  maya #include <math.h>
     12  1.1  maya #include <stdio.h>
     13  1.1  maya #include <stdlib.h>
     14  1.1  maya 
     15  1.1  maya /*#pragma STDC FENV_ACCESS ON gcc?? */
     16  1.1  maya 
     17  1.1  maya #define INT 9223L
     18  1.1  maya 
     19  1.1  maya #define EPSILON 0.001
     20  1.1  maya 
     21  1.1  maya static const struct {
     22  1.1  maya 	int round_mode;
     23  1.1  maya 	double input;
     24  1.1  maya 	long int expected;
     25  1.1  maya } values[] = {
     26  1.1  maya 	{ FE_DOWNWARD,		3.7,		3},
     27  1.1  maya 	{ FE_DOWNWARD,		-3.7,		-4},
     28  1.1  maya 	{ FE_DOWNWARD,		+0,		0},
     29  1.1  maya 	{ FE_DOWNWARD,		-INT-0.01,	-INT-1},
     30  1.1  maya 	{ FE_DOWNWARD,		+INT-0.01,	INT-1},
     31  1.1  maya 	{ FE_DOWNWARD,		-INT+0.01,	-INT},
     32  1.1  maya 	{ FE_DOWNWARD,		+INT+0.01,	INT},
     33  1.1  maya #if 0 /* cpu bugs? */
     34  1.1  maya 	{ FE_DOWNWARD,		-0,		-1},
     35  1.1  maya 
     36  1.1  maya 	{ FE_UPWARD,		+0,		1},
     37  1.1  maya #endif
     38  1.1  maya 	{ FE_UPWARD,		-0,		0},
     39  1.1  maya 	{ FE_UPWARD,		-123.7,		-123},
     40  1.1  maya 	{ FE_UPWARD,		123.999,	124},
     41  1.1  maya 	{ FE_UPWARD,		-INT-0.01,	-INT},
     42  1.1  maya 	{ FE_UPWARD,		+INT-0.01,	INT},
     43  1.1  maya 	{ FE_UPWARD,		-INT+0.01,	-INT+1},
     44  1.1  maya 	{ FE_UPWARD,		+INT+0.01,	INT+1},
     45  1.1  maya 
     46  1.1  maya 	{ FE_TOWARDZERO,	1.99,		1},
     47  1.1  maya 	{ FE_TOWARDZERO,	-1.99,		-1},
     48  1.1  maya 	{ FE_TOWARDZERO,	0.2,		0},
     49  1.1  maya 	{ FE_TOWARDZERO,	INT+0.01,	INT},
     50  1.1  maya 	{ FE_TOWARDZERO,	INT-0.01,	INT - 1},
     51  1.1  maya 	{ FE_TOWARDZERO,	-INT+0.01,	-INT + 1},
     52  1.1  maya 	{ FE_TOWARDZERO,	+0,		0},
     53  1.1  maya 	{ FE_TOWARDZERO,	-0,		0},
     54  1.1  maya 
     55  1.1  maya 	{ FE_TONEAREST,		-INT-0.01,	-INT},
     56  1.1  maya 	{ FE_TONEAREST,		+INT-0.01,	INT},
     57  1.1  maya 	{ FE_TONEAREST,		-INT+0.01,	-INT},
     58  1.1  maya 	{ FE_TONEAREST,		+INT+0.01,	INT},
     59  1.1  maya 	{ FE_TONEAREST,		-INT-0.501,	-INT-1},
     60  1.1  maya 	{ FE_TONEAREST,		+INT-0.501,	INT-1},
     61  1.1  maya 	{ FE_TONEAREST,		-INT+0.501,	-INT+1},
     62  1.1  maya 	{ FE_TONEAREST,		+INT+0.501,	INT+1},
     63  1.1  maya 	{ FE_TONEAREST,		+0,		0},
     64  1.1  maya 	{ FE_TONEAREST,		-0,		0},
     65  1.1  maya };
     66  1.1  maya 
     67  1.1  maya ATF_TC(fe_round);
     68  1.1  maya ATF_TC_HEAD(fe_round, tc)
     69  1.1  maya {
     70  1.1  maya 	atf_tc_set_md_var(tc, "descr","Checking IEEE 754 rounding modes using lrint");
     71  1.1  maya }
     72  1.1  maya 
     73  1.1  maya ATF_TC_BODY(fe_round, tc)
     74  1.1  maya {
     75  1.1  maya 	long int received;
     76  1.1  maya 
     77  1.1  maya 	for (unsigned int i = 0; i < __arraycount(values); i++) {
     78  1.1  maya 		fesetround(values[i].round_mode);
     79  1.1  maya 
     80  1.1  maya 		received = lrint(values[i].input);
     81  1.1  maya 		ATF_CHECK_MSG(
     82  1.2  maya 		    (labs(received - values[i].expected) < EPSILON),
     83  1.1  maya 		    "lrint rounding wrong, difference too large\n"
     84  1.1  maya 		    "input: %f (index %d): got %ld, expected %ld\n",
     85  1.1  maya 		    values[i].input, i, received, values[i].expected);
     86  1.1  maya 
     87  1.1  maya 		/* Do we get the same rounding mode out? */
     88  1.1  maya 		ATF_CHECK_MSG(
     89  1.1  maya 		    (fegetround() == values[i].round_mode),
     90  1.1  maya 		    "Didn't get the same rounding mode out!\n"
     91  1.1  maya 		    "(index %d) fed in %d rounding mode, got %d out\n",
     92  1.3    he 		    i, values[i].round_mode, fegetround());
     93  1.1  maya 	}
     94  1.1  maya }
     95  1.1  maya 
     96  1.4    he ATF_TC(fe_nearbyint);
     97  1.4    he ATF_TC_HEAD(fe_nearbyint, tc)
     98  1.4    he {
     99  1.4    he 	atf_tc_set_md_var(tc, "descr","Checking IEEE 754 rounding modes using nearbyint");
    100  1.4    he }
    101  1.4    he 
    102  1.4    he ATF_TC_BODY(fe_nearbyint, tc)
    103  1.4    he {
    104  1.4    he 	double received;
    105  1.4    he 
    106  1.4    he 	for (unsigned int i = 0; i < __arraycount(values); i++) {
    107  1.4    he 		fesetround(values[i].round_mode);
    108  1.4    he 
    109  1.4    he 		received = nearbyint(values[i].input);
    110  1.4    he 		ATF_CHECK_MSG(
    111  1.4    he 		    (fabs(received - values[i].expected) < EPSILON),
    112  1.4    he 		    "nearbyint rounding wrong, difference too large\n"
    113  1.4    he 		    "input: %f (index %d): got %f, expected %ld\n",
    114  1.4    he 		    values[i].input, i, received, values[i].expected);
    115  1.4    he 
    116  1.4    he 		/* Do we get the same rounding mode out? */
    117  1.4    he 		ATF_CHECK_MSG(
    118  1.4    he 		    (fegetround() == values[i].round_mode),
    119  1.4    he 		    "Didn't get the same rounding mode out!\n"
    120  1.4    he 		    "(index %d) fed in %d rounding mode, got %d out\n",
    121  1.4    he 		    i, values[i].round_mode, fegetround());
    122  1.4    he 	}
    123  1.4    he }
    124  1.4    he 
    125  1.1  maya ATF_TP_ADD_TCS(tp)
    126  1.1  maya {
    127  1.1  maya 
    128  1.1  maya 	ATF_TP_ADD_TC(tp, fe_round);
    129  1.4    he 	ATF_TP_ADD_TC(tp, fe_nearbyint);
    130  1.1  maya 
    131  1.1  maya 	return atf_no_error();
    132  1.1  maya }
    133  1.1  maya #else
    134  1.1  maya ATF_TC(t_nofe_round);
    135  1.1  maya 
    136  1.1  maya ATF_TC_HEAD(t_nofe_round, tc)
    137  1.1  maya {
    138  1.1  maya 	atf_tc_set_md_var(tc, "descr",
    139  1.1  maya 	    "dummy test case - no fenv.h support");
    140  1.1  maya }
    141  1.1  maya 
    142  1.4    he ATF_TC_BODY(t_nofe_round, tc)
    143  1.4    he {
    144  1.4    he 	atf_tc_skip("no fenv.h support on this architecture");
    145  1.4    he }
    146  1.1  maya 
    147  1.4    he ATF_TC_HEAD(t_nofe_nearbyint, tc)
    148  1.4    he {
    149  1.4    he 	atf_tc_set_md_var(tc, "descr",
    150  1.4    he 	    "dummy test case - no fenv.h support");
    151  1.4    he }
    152  1.4    he 
    153  1.4    he ATF_TC_BODY(t_nofe_nearbyint, tc)
    154  1.1  maya {
    155  1.1  maya 	atf_tc_skip("no fenv.h support on this architecture");
    156  1.1  maya }
    157  1.1  maya 
    158  1.4    he 
    159  1.1  maya ATF_TP_ADD_TCS(tp)
    160  1.1  maya {
    161  1.1  maya 	ATF_TP_ADD_TC(tp, t_nofe_round);
    162  1.4    he 	ATF_TP_ADD_TC(tp, t_nofe_nearbyint);
    163  1.1  maya 	return atf_no_error();
    164  1.1  maya }
    165  1.1  maya 
    166  1.1  maya #endif
    167