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