1 
2 /* @(#)s_floor.c 5.1 93/09/24 */
3 /*
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunPro, a Sun Microsystems, Inc. business.
8  * Permission to use, copy, modify, and distribute this
9  * software is freely granted, provided that this notice
10  * is preserved.
11  * ====================================================
12  */
13 
14 /*
15 FUNCTION
16 <<floor>>, <<floorf>>, <<ceil>>, <<ceilf>>---floor and ceiling
17 INDEX
18 	floor
19 INDEX
20 	floorf
21 INDEX
22 	ceil
23 INDEX
24 	ceilf
25 
26 SYNOPSIS
27 	#include <math.h>
28 	double floor(double <[x]>);
29         float floorf(float <[x]>);
30         double ceil(double <[x]>);
31         float ceilf(float <[x]>);
32 
33 DESCRIPTION
34 <<floor>> and <<floorf>> find
35 @tex
36 $\lfloor x \rfloor$,
37 @end tex
38 the nearest integer less than or equal to <[x]>.
39 <<ceil>> and <<ceilf>> find
40 @tex
41 $\lceil x\rceil$,
42 @end tex
43 the nearest integer greater than or equal to <[x]>.
44 
45 RETURNS
46 <<floor>> and <<ceil>> return the integer result as a double.
47 <<floorf>> and <<ceilf>> return the integer result as a float.
48 
49 PORTABILITY
50 <<floor>> and <<ceil>> are ANSI.
51 <<floorf>> and <<ceilf>> are extensions.
52 
53 
54 */
55 
56 /*
57  * floor(x)
58  * Return x rounded toward -inf to integral value
59  * Method:
60  *	Bit twiddling.
61  * Exception:
62  *	Inexact flag raised if x not equal to floor(x).
63  */
64 
65 #include "fdlibm.h"
66 
67 #ifdef _NEED_FLOAT64
68 
69 __float64
floor64(__float64 x)70 floor64(__float64 x)
71 {
72     __int32_t i0, i1, j0, j;
73     __uint32_t i;
74     EXTRACT_WORDS(i0, i1, x);
75     j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
76     if (j0 < 20) {
77         if (j0 < 0) {
78             if (i0 >= 0) {
79                 i0 = i1 = 0;
80             } else if (((i0 & 0x7fffffff) | i1) != 0) {
81                 i0 = 0xbff00000;
82                 i1 = 0;
83             }
84         } else {
85             i = (0x000fffff) >> j0;
86             if (((i0 & i) | i1) == 0)
87                 return x; /* x is integral */
88             if (i0 < 0)
89                 i0 += (0x00100000) >> j0;
90             i0 &= (~i);
91             i1 = 0;
92         }
93     } else if (j0 > 51) {
94         if (j0 == 0x400)
95             return x + x; /* inf or NaN */
96         else
97             return x; /* x is integral */
98     } else {
99         i = ((__uint32_t)(0xffffffff)) >> (j0 - 20);
100         if ((i1 & i) == 0)
101             return x; /* x is integral */
102         if (i0 < 0) {
103             if (j0 == 20)
104                 i0 += 1;
105             else {
106                 j = i1 + ((__uint32_t) 1 << (52 - j0));
107                 if ((__uint32_t) j < (__uint32_t) i1)
108                     i0 += 1; /* got a carry */
109                 i1 = j;
110             }
111         }
112         i1 &= (~i);
113     }
114     INSERT_WORDS(x, i0, i1);
115     return x;
116 }
117 
118 _MATH_ALIAS_d_d(floor)
119 
120 #endif /* _NEED_FLOAT64 */
121