1 |
1325 |
phoenix |
/*******************************************************************************
|
2 |
|
|
* *
|
3 |
|
|
* File ceilfloor.c, *
|
4 |
|
|
* Function ceil(x) and floor(x), *
|
5 |
|
|
* Implementation of ceil and floor for the PowerPC. *
|
6 |
|
|
* *
|
7 |
|
|
* Copyright © 1991 Apple Computer, Inc. All rights reserved. *
|
8 |
|
|
* *
|
9 |
|
|
* Written by Ali Sazegari, started on November 1991, *
|
10 |
|
|
* *
|
11 |
|
|
* based on math.h, library code for Macintoshes with a 68881/68882 *
|
12 |
|
|
* by Jim Thomas. *
|
13 |
|
|
* *
|
14 |
|
|
* W A R N I N G: This routine expects a 64 bit double model. *
|
15 |
|
|
* *
|
16 |
|
|
* December 03 1992: first rs6000 port. *
|
17 |
|
|
* July 14 1993: comment changes and addition of #pragma fenv_access. *
|
18 |
|
|
* May 06 1997: port of the ibm/taligent ceil and floor routines. *
|
19 |
|
|
* April 11 2001: first port to os x using gcc. *
|
20 |
|
|
* June 13 2001: replaced __setflm with in-line assembly *
|
21 |
|
|
* *
|
22 |
|
|
*******************************************************************************/
|
23 |
|
|
|
24 |
|
|
static const double twoTo52 = 4503599627370496.0;
|
25 |
|
|
static const unsigned long signMask = 0x80000000ul;
|
26 |
|
|
|
27 |
|
|
typedef union
|
28 |
|
|
{
|
29 |
|
|
struct {
|
30 |
|
|
#if defined(__BIG_ENDIAN__)
|
31 |
|
|
unsigned long int hi;
|
32 |
|
|
unsigned long int lo;
|
33 |
|
|
#else
|
34 |
|
|
unsigned long int lo;
|
35 |
|
|
unsigned long int hi;
|
36 |
|
|
#endif
|
37 |
|
|
} words;
|
38 |
|
|
double dbl;
|
39 |
|
|
} DblInHex;
|
40 |
|
|
|
41 |
|
|
/*******************************************************************************
|
42 |
|
|
* Functions needed for the computation. *
|
43 |
|
|
*******************************************************************************/
|
44 |
|
|
|
45 |
|
|
/*******************************************************************************
|
46 |
|
|
* Floor(x) returns the largest integer not greater than x. *
|
47 |
|
|
*******************************************************************************/
|
48 |
|
|
|
49 |
|
|
double floor ( double x )
|
50 |
|
|
{
|
51 |
|
|
DblInHex xInHex,OldEnvironment;
|
52 |
|
|
register double y;
|
53 |
|
|
register unsigned long int xhi;
|
54 |
|
|
register long int target;
|
55 |
|
|
|
56 |
|
|
xInHex.dbl = x;
|
57 |
|
|
xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x|
|
58 |
|
|
target = ( xInHex.words.hi < signMask );
|
59 |
|
|
|
60 |
|
|
if ( xhi < 0x43300000ul )
|
61 |
|
|
/*******************************************************************************
|
62 |
|
|
* Is |x| < 2.0^52? *
|
63 |
|
|
*******************************************************************************/
|
64 |
|
|
{
|
65 |
|
|
if ( xhi < 0x3ff00000ul )
|
66 |
|
|
/*******************************************************************************
|
67 |
|
|
* Is |x| < 1.0? *
|
68 |
|
|
*******************************************************************************/
|
69 |
|
|
{
|
70 |
|
|
if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case
|
71 |
|
|
return ( x );
|
72 |
|
|
else
|
73 |
|
|
{ // inexact case
|
74 |
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
75 |
|
|
OldEnvironment.words.lo |= 0x02000000ul;
|
76 |
|
|
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
|
77 |
|
|
if ( target )
|
78 |
|
|
return ( 0.0 );
|
79 |
|
|
else
|
80 |
|
|
return ( -1.0 );
|
81 |
|
|
}
|
82 |
|
|
}
|
83 |
|
|
/*******************************************************************************
|
84 |
|
|
* Is 1.0 < |x| < 2.0^52? *
|
85 |
|
|
*******************************************************************************/
|
86 |
|
|
if ( target )
|
87 |
|
|
{
|
88 |
|
|
y = ( x + twoTo52 ) - twoTo52; // round at binary pt.
|
89 |
|
|
if ( y > x )
|
90 |
|
|
return ( y - 1.0 );
|
91 |
|
|
else
|
92 |
|
|
return ( y );
|
93 |
|
|
}
|
94 |
|
|
|
95 |
|
|
else
|
96 |
|
|
{
|
97 |
|
|
y = ( x - twoTo52 ) + twoTo52; // round at binary pt.
|
98 |
|
|
if ( y > x )
|
99 |
|
|
return ( y - 1.0 );
|
100 |
|
|
else
|
101 |
|
|
return ( y );
|
102 |
|
|
}
|
103 |
|
|
}
|
104 |
|
|
/*******************************************************************************
|
105 |
|
|
* |x| >= 2.0^52 or x is a NaN. *
|
106 |
|
|
*******************************************************************************/
|
107 |
|
|
return ( x );
|
108 |
|
|
}
|
109 |
|
|
|