1 |
1325 |
phoenix |
/*******************************************************************************
|
2 |
|
|
** File: rndint.c
|
3 |
|
|
**
|
4 |
|
|
** Contains: C source code for implementations of floating-point
|
5 |
|
|
** functions which round to integral value or format, as
|
6 |
|
|
** defined in header <fp.h>. In particular, this file
|
7 |
|
|
** contains implementations of functions rint, nearbyint,
|
8 |
|
|
** rinttol, round, roundtol, trunc, modf and modfl. This file
|
9 |
|
|
** targets PowerPC or Power platforms.
|
10 |
|
|
**
|
11 |
|
|
** Written by: A. Sazegari, Apple AltiVec Group
|
12 |
|
|
** Created originally by Jon Okada, Apple Numerics Group
|
13 |
|
|
**
|
14 |
|
|
** Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved
|
15 |
|
|
**
|
16 |
|
|
** Change History (most recent first):
|
17 |
|
|
**
|
18 |
|
|
** 13 Jul 01 ram replaced --setflm calls with inline assembly
|
19 |
|
|
** 03 Mar 01 ali first port to os x using gcc, added the crucial __setflm
|
20 |
|
|
** definition.
|
21 |
|
|
** 1. removed double_t, put in double for now.
|
22 |
|
|
** 2. removed iclass from nearbyint.
|
23 |
|
|
** 3. removed wrong comments intrunc.
|
24 |
|
|
** 4.
|
25 |
|
|
** 13 May 97 ali made performance improvements in rint, rinttol, roundtol
|
26 |
|
|
** and trunc by folding some of the taligent ideas into this
|
27 |
|
|
** implementation. nearbyint is faster than the one in taligent,
|
28 |
|
|
** rint is more elegant, but slower by %30 than the taligent one.
|
29 |
|
|
** 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c
|
30 |
|
|
** 15 Sep 94 ali Major overhaul and performance improvements of all functions.
|
31 |
|
|
** 20 Jul 94 PAF New faster version
|
32 |
|
|
** 16 Jul 93 ali Added the modfl function.
|
33 |
|
|
** 18 Feb 93 ali Changed the return value of fenv functions
|
34 |
|
|
** feclearexcept and feraiseexcept to their new
|
35 |
|
|
** NCEG X3J11.1/93-001 definitions.
|
36 |
|
|
** 16 Dec 92 JPO Removed __itrunc implementation to a
|
37 |
|
|
** separate file.
|
38 |
|
|
** 15 Dec 92 JPO Added __itrunc implementation and modified
|
39 |
|
|
** rinttol to include conversion from double
|
40 |
|
|
** to long int format. Modified roundtol to
|
41 |
|
|
** call __itrunc.
|
42 |
|
|
** 10 Dec 92 JPO Added modf (double) implementation.
|
43 |
|
|
** 04 Dec 92 JPO First created.
|
44 |
|
|
**
|
45 |
|
|
*******************************************************************************/
|
46 |
|
|
|
47 |
|
|
#include <limits.h>
|
48 |
|
|
#include <math.h>
|
49 |
|
|
|
50 |
|
|
#define SET_INVALID 0x01000000UL
|
51 |
|
|
|
52 |
|
|
typedef union
|
53 |
|
|
{
|
54 |
|
|
struct {
|
55 |
|
|
#if defined(__BIG_ENDIAN__)
|
56 |
|
|
unsigned long int hi;
|
57 |
|
|
unsigned long int lo;
|
58 |
|
|
#else
|
59 |
|
|
unsigned long int lo;
|
60 |
|
|
unsigned long int hi;
|
61 |
|
|
#endif
|
62 |
|
|
} words;
|
63 |
|
|
double dbl;
|
64 |
|
|
} DblInHex;
|
65 |
|
|
|
66 |
|
|
static const unsigned long int signMask = 0x80000000ul;
|
67 |
|
|
static const double twoTo52 = 4503599627370496.0;
|
68 |
|
|
static const double doubleToLong = 4503603922337792.0; // 2^52
|
69 |
|
|
static const DblInHex Huge = {{ 0x7FF00000, 0x00000000 }};
|
70 |
|
|
static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }};
|
71 |
|
|
|
72 |
|
|
/*******************************************************************************
|
73 |
|
|
* *
|
74 |
|
|
* The function rint rounds its double argument to integral value *
|
75 |
|
|
* according to the current rounding direction and returns the result in *
|
76 |
|
|
* double format. This function signals inexact if an ordered return *
|
77 |
|
|
* value is not equal to the operand. *
|
78 |
|
|
* *
|
79 |
|
|
********************************************************************************
|
80 |
|
|
* *
|
81 |
|
|
* This function calls: fabs. *
|
82 |
|
|
* *
|
83 |
|
|
*******************************************************************************/
|
84 |
|
|
|
85 |
|
|
/*******************************************************************************
|
86 |
|
|
* First, an elegant implementation. *
|
87 |
|
|
********************************************************************************
|
88 |
|
|
*
|
89 |
|
|
*double rint ( double x )
|
90 |
|
|
* {
|
91 |
|
|
* double y;
|
92 |
|
|
*
|
93 |
|
|
* y = twoTo52.fval;
|
94 |
|
|
*
|
95 |
|
|
* if ( fabs ( x ) >= y ) // huge case is exact
|
96 |
|
|
* return x;
|
97 |
|
|
* if ( x < 0 ) y = -y; // negative case
|
98 |
|
|
* y = ( x + y ) - y; // force rounding
|
99 |
|
|
* if ( y == 0.0 ) // zero results mirror sign of x
|
100 |
|
|
* y = copysign ( y, x );
|
101 |
|
|
* return ( y );
|
102 |
|
|
* }
|
103 |
|
|
********************************************************************************
|
104 |
|
|
* Now a bit twidling version that is about %30 faster. *
|
105 |
|
|
*******************************************************************************/
|
106 |
|
|
|
107 |
|
|
double rint ( double x )
|
108 |
|
|
{
|
109 |
|
|
DblInHex argument;
|
110 |
|
|
register double y;
|
111 |
|
|
unsigned long int xHead;
|
112 |
|
|
register long int target;
|
113 |
|
|
|
114 |
|
|
argument.dbl = x;
|
115 |
|
|
xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x|
|
116 |
|
|
target = ( argument.words.hi < signMask ); // flags positive sign
|
117 |
|
|
|
118 |
|
|
if ( xHead < 0x43300000ul )
|
119 |
|
|
/*******************************************************************************
|
120 |
|
|
* Is |x| < 2.0^52? *
|
121 |
|
|
*******************************************************************************/
|
122 |
|
|
{
|
123 |
|
|
if ( xHead < 0x3ff00000ul )
|
124 |
|
|
/*******************************************************************************
|
125 |
|
|
* Is |x| < 1.0? *
|
126 |
|
|
*******************************************************************************/
|
127 |
|
|
{
|
128 |
|
|
if ( target )
|
129 |
|
|
y = ( x + twoTo52 ) - twoTo52; // round at binary point
|
130 |
|
|
else
|
131 |
|
|
y = ( x - twoTo52 ) + twoTo52; // round at binary point
|
132 |
|
|
if ( y == 0.0 )
|
133 |
|
|
{ // fix sign of zero result
|
134 |
|
|
if ( target )
|
135 |
|
|
return ( 0.0 );
|
136 |
|
|
else
|
137 |
|
|
return ( -0.0 );
|
138 |
|
|
}
|
139 |
|
|
return y;
|
140 |
|
|
}
|
141 |
|
|
|
142 |
|
|
/*******************************************************************************
|
143 |
|
|
* Is 1.0 < |x| < 2.0^52? *
|
144 |
|
|
*******************************************************************************/
|
145 |
|
|
|
146 |
|
|
if ( target )
|
147 |
|
|
return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt.
|
148 |
|
|
else
|
149 |
|
|
return ( ( x - twoTo52 ) + twoTo52 );
|
150 |
|
|
}
|
151 |
|
|
|
152 |
|
|
/*******************************************************************************
|
153 |
|
|
* |x| >= 2.0^52 or x is a NaN. *
|
154 |
|
|
*******************************************************************************/
|
155 |
|
|
return ( x );
|
156 |
|
|
}
|
157 |
|
|
|