xref: /csrg-svn/lib/libm/common_source/floor.c (revision 61291)
134122Sbostic /*
2*61291Sbostic  * Copyright (c) 1985, 1993
3*61291Sbostic  *	The Regents of the University of California.  All rights reserved.
434401Sbostic  *
542657Sbostic  * %sccs.include.redist.c%
634122Sbostic  */
724596Szliu 
834122Sbostic #ifndef lint
9*61291Sbostic static char sccsid[] = "@(#)floor.c	8.1 (Berkeley) 06/04/93";
1034122Sbostic #endif /* not lint */
1134122Sbostic 
1235679Sbostic #include "mathimpl.h"
1334401Sbostic 
1435679Sbostic vc(L, 4503599627370496.0E0 ,0000,5c00,0000,0000, 55, 1.0) /* 2**55 */
1535679Sbostic 
1635679Sbostic ic(L, 4503599627370496.0E0, 52, 1.0)			  /* 2**52 */
1735679Sbostic 
1835679Sbostic #ifdef vccast
1935679Sbostic #define	L	vccast(L)
2035679Sbostic #endif
2135679Sbostic 
2224596Szliu /*
2334401Sbostic  * floor(x) := the largest integer no larger than x;
2434401Sbostic  * ceil(x) := -floor(-x), for all real x.
2534401Sbostic  *
2634401Sbostic  * Note: Inexact will be signaled if x is not an integer, as is
2734401Sbostic  *	customary for IEEE 754.  No other signal can be emitted.
2824596Szliu  */
2924596Szliu double
3034401Sbostic floor(x)
3134401Sbostic double x;
3224596Szliu {
3356371Sbostic 	volatile double y;
3424596Szliu 
3534401Sbostic 	if (
3634401Sbostic #if !defined(vax)&&!defined(tahoe)
3734401Sbostic 		x != x ||	/* NaN */
3834401Sbostic #endif	/* !defined(vax)&&!defined(tahoe) */
3934401Sbostic 		x >= L)		/* already an even integer */
4034401Sbostic 		return x;
4134401Sbostic 	else if (x < (double)0)
4234401Sbostic 		return -ceil(-x);
4334401Sbostic 	else {			/* now 0 <= x < L */
4434401Sbostic 		y = L+x;		/* destructive store must be forced */
4534401Sbostic 		y -= L;			/* an integer, and |x-y| < 1 */
4634401Sbostic 		return x < y ? y-(double)1 : y;
4734401Sbostic 	}
4824596Szliu }
4924596Szliu 
5024596Szliu double
ceil(x)5134401Sbostic ceil(x)
5234401Sbostic double x;
5324596Szliu {
5456371Sbostic 	volatile double y;
5534401Sbostic 
5634401Sbostic 	if (
5734401Sbostic #if !defined(vax)&&!defined(tahoe)
5834401Sbostic 		x != x ||	/* NaN */
5934401Sbostic #endif	/* !defined(vax)&&!defined(tahoe) */
6034401Sbostic 		x >= L)		/* already an even integer */
6134401Sbostic 		return x;
6234401Sbostic 	else if (x < (double)0)
6334401Sbostic 		return -floor(-x);
6434401Sbostic 	else {			/* now 0 <= x < L */
6534401Sbostic 		y = L+x;		/* destructive store must be forced */
6634401Sbostic 		y -= L;			/* an integer, and |x-y| < 1 */
6734401Sbostic 		return x > y ? y+(double)1 : y;
6834401Sbostic 	}
6924596Szliu }
7024596Szliu 
7156371Sbostic #ifndef ns32000			/* rint() is in ./NATIONAL/support.s */
7224596Szliu /*
7324596Szliu  * algorithm for rint(x) in pseudo-pascal form ...
7424596Szliu  *
7524596Szliu  * real rint(x): real x;
7624596Szliu  *	... delivers integer nearest x in direction of prevailing rounding
7724596Szliu  *	... mode
7824596Szliu  * const	L = (last consecutive integer)/2
7924596Szliu  * 	  = 2**55; for VAX D
8024596Szliu  * 	  = 2**52; for IEEE 754 Double
8124596Szliu  * real	s,t;
8224596Szliu  * begin
8324596Szliu  * 	if x != x then return x;		... NaN
8424596Szliu  * 	if |x| >= L then return x;		... already an integer
8524596Szliu  * 	s := copysign(L,x);
8624596Szliu  * 	t := x + s;				... = (x+s) rounded to integer
8724596Szliu  * 	return t - s
8824596Szliu  * end;
8924596Szliu  *
9024596Szliu  * Note: Inexact will be signaled if x is not an integer, as is
9124596Szliu  *	customary for IEEE 754.  No other signal can be emitted.
9224596Szliu  */
9324596Szliu double
rint(x)9424596Szliu rint(x)
9524596Szliu double x;
9624596Szliu {
9756371Sbostic 	double s;
9856371Sbostic 	volatile double t;
9935679Sbostic 	const double one = 1.0;
10035679Sbostic 
10131853Szliu #if !defined(vax)&&!defined(tahoe)
10224596Szliu 	if (x != x)				/* NaN */
10324596Szliu 		return (x);
10431853Szliu #endif	/* !defined(vax)&&!defined(tahoe) */
10524596Szliu 	if (copysign(x,one) >= L)		/* already an integer */
10624596Szliu 	    return (x);
10724596Szliu 	s = copysign(L,x);
10824596Szliu 	t = x + s;				/* x+s rounded to integer */
10924596Szliu 	return (t - s);
11024596Szliu }
11131853Szliu #endif	/* not national */
112