1140088Sdas/*-
2140088Sdas * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
3140088Sdas * All rights reserved.
4140088Sdas *
5140088Sdas * Redistribution and use in source and binary forms, with or without
6140088Sdas * modification, are permitted provided that the following conditions
7140088Sdas * are met:
8140088Sdas * 1. Redistributions of source code must retain the above copyright
9140088Sdas *    notice, this list of conditions and the following disclaimer.
10140088Sdas * 2. Redistributions in binary form must reproduce the above copyright
11140088Sdas *    notice, this list of conditions and the following disclaimer in the
12140088Sdas *    documentation and/or other materials provided with the distribution.
13140088Sdas *
14140088Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15140088Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16140088Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17140088Sdas * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18140088Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19140088Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20140088Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21140088Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22140088Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23140088Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24140088Sdas * SUCH DAMAGE.
25140088Sdas */
26140088Sdas
27140088Sdas#include <sys/cdefs.h>
28140088Sdas#include <fenv.h>
29140088Sdas#include <math.h>
30140088Sdas
31140088Sdas#ifndef type
32140088Sdas__FBSDID("$FreeBSD$");
33140088Sdas#define type		double
34140088Sdas#define	roundit		rint
35140088Sdas#define dtype		long
36140088Sdas#define	fn		lrint
37140088Sdas#endif
38140088Sdas
39140088Sdas/*
40140088Sdas * C99 says we should not raise a spurious inexact exception when an
41140088Sdas * invalid exception is raised.  Unfortunately, the set of inputs
42140088Sdas * that overflows depends on the rounding mode when 'dtype' has more
43140088Sdas * significant bits than 'type'.  Hence, we bend over backwards for the
44140088Sdas * sake of correctness; an MD implementation could be more efficient.
45140088Sdas */
46140088Sdasdtype
47140088Sdasfn(type x)
48140088Sdas{
49140088Sdas	fenv_t env;
50140088Sdas	dtype d;
51140088Sdas
52140088Sdas	feholdexcept(&env);
53140088Sdas	d = (dtype)roundit(x);
54140088Sdas	if (fetestexcept(FE_INVALID))
55140088Sdas		feclearexcept(FE_INEXACT);
56140088Sdas	feupdateenv(&env);
57140088Sdas	return (d);
58140088Sdas}
59