xref: /netbsd-src/lib/libm/noieee_src/n_floor.c (revision 078777ba386e978f3382328681683a256fdab0ad)
1 /*      $NetBSD: n_floor.c,v 1.9 2024/05/08 02:08:11 riastradh Exp $ */
2 /*
3  * Copyright (c) 1985, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. 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  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #ifndef lint
32 #if 0
33 static char sccsid[] = "@(#)floor.c	8.1 (Berkeley) 6/4/93";
34 #endif
35 #endif /* not lint */
36 
37 #define _LIBM_STATIC
38 #include "mathimpl.h"
39 
40 vc(L, 4503599627370496.0E0 ,0000,5c00,0000,0000, 55, 1.0) /* 2**55 */
41 
42 ic(L, 4503599627370496.0E0, 52, 1.0)			  /* 2**52 */
43 
44 #ifdef vccast
45 #define	L	vccast(L)
46 #endif
47 
__weak_alias(ceill,ceil)48 __weak_alias(ceill, ceil)
49 __weak_alias(floorl, floor)
50 __weak_alias(truncl, trunc)
51 __weak_alias(rintl, rint)
52 
53 /*
54  * floor(x) := the largest integer no larger than x;
55  * ceil(x) := -floor(-x), for all real x.
56  *
57  * Note: Inexact will be signaled if x is not an integer, as is
58  *	customary for IEEE 754.  No other signal can be emitted.
59  */
60 double
61 floor(double x)
62 {
63 	volatile double y;
64 
65 	if (
66 #if !defined(__vax__)&&!defined(tahoe)
67 		x != x ||	/* NaN */
68 #endif	/* !defined(__vax__)&&!defined(tahoe) */
69 		x >= L)		/* already an even integer */
70 		return x;
71 	else if (x < (double)0)
72 		return -ceil(-x);
73 	else {			/* now 0 <= x < L */
74 		y = L+x;		/* destructive store must be forced */
75 		y -= L;			/* an integer, and |x-y| < 1 */
76 		return x < y ? y-(double)1 : y;
77 	}
78 }
79 
80 float
floorf(float x)81 floorf(float x)
82 {
83 	return floor((double)x);
84 }
85 
86 double
ceil(double x)87 ceil(double x)
88 {
89 	volatile double y;
90 
91 	if (
92 #if !defined(__vax__)&&!defined(tahoe)
93 		x != x ||	/* NaN */
94 #endif	/* !defined(__vax__)&&!defined(tahoe) */
95 		x >= L)		/* already an even integer */
96 		return x;
97 	else if (x < (double)0)
98 		return -floor(-x);
99 	else {			/* now 0 <= x < L */
100 		y = L+x;		/* destructive store must be forced */
101 		y -= L;			/* an integer, and |x-y| < 1 */
102 		return x > y ? y+(double)1 : y;
103 	}
104 }
105 
106 float
ceilf(float x)107 ceilf(float x)
108 {
109 	return ceil((double)x);
110 }
111 
112 /*
113  * algorithm for rint(x) in pseudo-pascal form ...
114  *
115  * real rint(x): real x;
116  *	... delivers integer nearest x in direction of prevailing rounding
117  *	... mode
118  * const	L = (last consecutive integer)/2
119  * 	  = 2**55; for VAX D
120  * 	  = 2**52; for IEEE 754 Double
121  * real	s,t;
122  * begin
123  * 	if x != x then return x;		... NaN
124  * 	if |x| >= L then return x;		... already an integer
125  * 	s := copysign(L,x);
126  * 	t := x + s;				... = (x+s) rounded to integer
127  * 	return t - s
128  * end;
129  *
130  * Note: Inexact will be signaled if x is not an integer, as is
131  *	customary for IEEE 754.  No other signal can be emitted.
132  */
133 double
rint(double x)134 rint(double x)
135 {
136 	double s;
137 	volatile double t;
138 	const double one = 1.0;
139 
140 #if !defined(__vax__)&&!defined(tahoe)
141 	if (x != x)				/* NaN */
142 		return (x);
143 #endif	/* !defined(__vax__)&&!defined(tahoe) */
144 	if (copysign(x,one) >= L)		/* already an integer */
145 	    return (x);
146 	s = copysign(L,x);
147 	t = x + s;				/* x+s rounded to integer */
148 	return (t - s);
149 }
150 
151 float
rintf(float x)152 rintf(float x)
153 {
154 	return rint((double)x);
155 }
156 
157 long
lrint(double x)158 lrint(double x)
159 {
160 	double s;
161 	volatile double t;
162 	const double one = 1.0;
163 
164 #if !defined(__vax__)&&!defined(tahoe)
165 	if (x != x)				/* NaN */
166 		return (x);
167 #endif	/* !defined(__vax__)&&!defined(tahoe) */
168 	if (copysign(x,one) >= L)		/* already an integer */
169 	    return (x);
170 	s = copysign(L,x);
171 	t = x + s;				/* x+s rounded to integer */
172 	return (t - s);
173 }
174 
175 long long
llrint(double x)176 llrint(double x)
177 {
178 	double s;
179 	volatile double t;
180 	const double one = 1.0;
181 
182 #if !defined(__vax__)&&!defined(tahoe)
183 	if (x != x)				/* NaN */
184 		return (x);
185 #endif	/* !defined(__vax__)&&!defined(tahoe) */
186 	if (copysign(x,one) >= L)		/* already an integer */
187 	    return (x);
188 	s = copysign(L,x);
189 	t = x + s;				/* x+s rounded to integer */
190 	return (t - s);
191 }
192 
193 long
lrintf(float x)194 lrintf(float x)
195 {
196 	float s;
197 	volatile float t;
198 	const float one = 1.0;
199 
200 #if !defined(__vax__)&&!defined(tahoe)
201 	if (x != x)				/* NaN */
202 		return (x);
203 #endif	/* !defined(__vax__)&&!defined(tahoe) */
204 	if (copysign(x,one) >= L)		/* already an integer */
205 	    return (x);
206 	s = copysign(L,x);
207 	t = x + s;				/* x+s rounded to integer */
208 	return (t - s);
209 }
210 
211 long long
llrintf(float x)212 llrintf(float x)
213 {
214 	float s;
215 	volatile float t;
216 	const float one = 1.0;
217 
218 #if !defined(__vax__)&&!defined(tahoe)
219 	if (x != x)				/* NaN */
220 		return (x);
221 #endif	/* !defined(__vax__)&&!defined(tahoe) */
222 	if (copysign(x,one) >= L)		/* already an integer */
223 	    return (x);
224 	s = copysign(L,x);
225 	t = x + s;				/* x+s rounded to integer */
226 	return (t - s);
227 }
228 
229 double
trunc(double x)230 trunc(double x)
231 {
232 	return x < 0 ? ceil(x) : floor(x);
233 }
234 
235 float
truncf(float x)236 truncf(float x)
237 {
238 	return x < 0 ? ceilf(x) : floorf(x);
239 }
240