1311970Sngie/* 2311970Sngie * Written by Maya Rashish <maya@NetBSD.org> 3311970Sngie * Public domain. 4311970Sngie * 5311970Sngie * Testing IEEE-754 rounding modes (and lrint) 6311970Sngie */ 7311970Sngie 8311970Sngie#include <atf-c.h> 9311970Sngie#include <fenv.h> 10311970Sngie#ifdef __HAVE_FENV 11311970Sngie#include <math.h> 12311970Sngie#include <stdio.h> 13311970Sngie#include <stdlib.h> 14311970Sngie 15311970Sngie/*#pragma STDC FENV_ACCESS ON gcc?? */ 16311970Sngie 17311970Sngie#define INT 9223L 18311970Sngie 19311970Sngie#define EPSILON 0.001 20311970Sngie 21311970Sngiestatic const struct { 22311970Sngie int round_mode; 23311970Sngie double input; 24311970Sngie long int expected; 25311970Sngie} values[] = { 26311970Sngie { FE_DOWNWARD, 3.7, 3}, 27311970Sngie { FE_DOWNWARD, -3.7, -4}, 28311970Sngie { FE_DOWNWARD, +0, 0}, 29311970Sngie { FE_DOWNWARD, -INT-0.01, -INT-1}, 30311970Sngie { FE_DOWNWARD, +INT-0.01, INT-1}, 31311970Sngie { FE_DOWNWARD, -INT+0.01, -INT}, 32311970Sngie { FE_DOWNWARD, +INT+0.01, INT}, 33311970Sngie#if 0 /* cpu bugs? */ 34311970Sngie { FE_DOWNWARD, -0, -1}, 35311970Sngie 36311970Sngie { FE_UPWARD, +0, 1}, 37311970Sngie#endif 38311970Sngie { FE_UPWARD, -0, 0}, 39311970Sngie { FE_UPWARD, -123.7, -123}, 40311970Sngie { FE_UPWARD, 123.999, 124}, 41311970Sngie { FE_UPWARD, -INT-0.01, -INT}, 42311970Sngie { FE_UPWARD, +INT-0.01, INT}, 43311970Sngie { FE_UPWARD, -INT+0.01, -INT+1}, 44311970Sngie { FE_UPWARD, +INT+0.01, INT+1}, 45311970Sngie 46311970Sngie { FE_TOWARDZERO, 1.99, 1}, 47311970Sngie { FE_TOWARDZERO, -1.99, -1}, 48311970Sngie { FE_TOWARDZERO, 0.2, 0}, 49311970Sngie { FE_TOWARDZERO, INT+0.01, INT}, 50311970Sngie { FE_TOWARDZERO, INT-0.01, INT - 1}, 51311970Sngie { FE_TOWARDZERO, -INT+0.01, -INT + 1}, 52311970Sngie { FE_TOWARDZERO, +0, 0}, 53311970Sngie { FE_TOWARDZERO, -0, 0}, 54311970Sngie 55311970Sngie { FE_TONEAREST, -INT-0.01, -INT}, 56311970Sngie { FE_TONEAREST, +INT-0.01, INT}, 57311970Sngie { FE_TONEAREST, -INT+0.01, -INT}, 58311970Sngie { FE_TONEAREST, +INT+0.01, INT}, 59311970Sngie { FE_TONEAREST, -INT-0.501, -INT-1}, 60311970Sngie { FE_TONEAREST, +INT-0.501, INT-1}, 61311970Sngie { FE_TONEAREST, -INT+0.501, -INT+1}, 62311970Sngie { FE_TONEAREST, +INT+0.501, INT+1}, 63311970Sngie { FE_TONEAREST, +0, 0}, 64311970Sngie { FE_TONEAREST, -0, 0}, 65311970Sngie}; 66311970Sngie 67311970SngieATF_TC(fe_round); 68311970SngieATF_TC_HEAD(fe_round, tc) 69311970Sngie{ 70311970Sngie atf_tc_set_md_var(tc, "descr","Checking IEEE 754 rounding modes using lrint"); 71311970Sngie} 72311970Sngie 73311970SngieATF_TC_BODY(fe_round, tc) 74311970Sngie{ 75311970Sngie long int received; 76311970Sngie 77311970Sngie for (unsigned int i = 0; i < __arraycount(values); i++) { 78311970Sngie fesetround(values[i].round_mode); 79311970Sngie 80311970Sngie received = lrint(values[i].input); 81311970Sngie ATF_CHECK_MSG( 82311970Sngie (labs(received - values[i].expected) < EPSILON), 83311970Sngie "lrint rounding wrong, difference too large\n" 84311970Sngie "input: %f (index %d): got %ld, expected %ld\n", 85311970Sngie values[i].input, i, received, values[i].expected); 86311970Sngie 87311970Sngie /* Do we get the same rounding mode out? */ 88311970Sngie ATF_CHECK_MSG( 89311970Sngie (fegetround() == values[i].round_mode), 90311970Sngie "Didn't get the same rounding mode out!\n" 91311970Sngie "(index %d) fed in %d rounding mode, got %d out\n", 92311970Sngie i, fegetround(), values[i].round_mode); 93311970Sngie } 94311970Sngie} 95311970Sngie 96311970SngieATF_TP_ADD_TCS(tp) 97311970Sngie{ 98311970Sngie 99311970Sngie ATF_TP_ADD_TC(tp, fe_round); 100311970Sngie 101311970Sngie return atf_no_error(); 102311970Sngie} 103311970Sngie#else 104311970SngieATF_TC(t_nofe_round); 105311970Sngie 106311970SngieATF_TC_HEAD(t_nofe_round, tc) 107311970Sngie{ 108311970Sngie atf_tc_set_md_var(tc, "descr", 109311970Sngie "dummy test case - no fenv.h support"); 110311970Sngie} 111311970Sngie 112311970Sngie 113311970SngieATF_TC_BODY(t_nofe_round, tc) 114311970Sngie{ 115311970Sngie atf_tc_skip("no fenv.h support on this architecture"); 116311970Sngie} 117311970Sngie 118311970SngieATF_TP_ADD_TCS(tp) 119311970Sngie{ 120311970Sngie ATF_TP_ADD_TC(tp, t_nofe_round); 121311970Sngie return atf_no_error(); 122311970Sngie} 123311970Sngie 124311970Sngie#endif 125