|
@@ -1,18 +1,18 @@
|
|
|
|
|
|
** File: rndint.c
|
|
|
-**
|
|
|
+**
|
|
|
** Contains: C source code for implementations of floating-point
|
|
|
** functions which round to integral value or format, as
|
|
|
** defined in header <fp.h>. In particular, this file
|
|
|
** contains implementations of functions rint, nearbyint,
|
|
|
** rinttol, round, roundtol, trunc, modf and modfl. This file
|
|
|
** targets PowerPC or Power platforms.
|
|
|
-**
|
|
|
+**
|
|
|
** Written by: A. Sazegari, Apple AltiVec Group
|
|
|
** Created originally by Jon Okada, Apple Numerics Group
|
|
|
-**
|
|
|
+**
|
|
|
** Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved
|
|
|
-**
|
|
|
+**
|
|
|
** Change History (most recent first):
|
|
|
**
|
|
|
** 13 Jul 01 ram replaced --setflm calls with inline assembly
|
|
@@ -21,7 +21,7 @@
|
|
|
** 1. removed double_t, put in double for now.
|
|
|
** 2. removed iclass from nearbyint.
|
|
|
** 3. removed wrong comments intrunc.
|
|
|
-** 4.
|
|
|
+** 4.
|
|
|
** 13 May 97 ali made performance improvements in rint, rinttol, roundtol
|
|
|
** and trunc by folding some of the taligent ideas into this
|
|
|
** implementation. nearbyint is faster than the one in taligent,
|
|
@@ -33,7 +33,7 @@
|
|
|
** 18 Feb 93 ali Changed the return value of fenv functions
|
|
|
** feclearexcept and feraiseexcept to their new
|
|
|
** NCEG X3J11.1/93-001 definitions.
|
|
|
-** 16 Dec 92 JPO Removed __itrunc implementation to a
|
|
|
+** 16 Dec 92 JPO Removed __itrunc implementation to a
|
|
|
** separate file.
|
|
|
** 15 Dec 92 JPO Added __itrunc implementation and modified
|
|
|
** rinttol to include conversion from double
|
|
@@ -41,7 +41,7 @@
|
|
|
** call __itrunc.
|
|
|
** 10 Dec 92 JPO Added modf (double) implementation.
|
|
|
** 04 Dec 92 JPO First created.
|
|
|
-**
|
|
|
+**
|
|
|
*******************************************************************************/
|
|
|
|
|
|
#include <limits.h>
|
|
@@ -81,14 +81,14 @@ static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }};
|
|
|
* This function calls fabs and copysign. *
|
|
|
* *
|
|
|
*******************************************************************************/
|
|
|
-
|
|
|
+
|
|
|
double nearbyint ( double x )
|
|
|
{
|
|
|
double y;
|
|
|
double OldEnvironment;
|
|
|
-
|
|
|
+
|
|
|
y = twoTo52;
|
|
|
-
|
|
|
+
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment));
|
|
|
|
|
|
if ( fabs ( x ) >= y )
|
|
@@ -99,9 +99,9 @@ double nearbyint ( double x )
|
|
|
y = copysign ( y, x );
|
|
|
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment ));
|
|
|
- return ( y );
|
|
|
+ return ( y );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
|
|
|
* *
|
|
|
* The function rinttol converts its double argument to integral value *
|
|
@@ -120,38 +120,38 @@ long int rinttol ( double x )
|
|
|
DblInHex argument, OldEnvironment;
|
|
|
unsigned long int xHead;
|
|
|
register long int target;
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = x;
|
|
|
target = ( argument.words.hi < signMask );
|
|
|
xHead = argument.words.hi & 0x7ffffffful;
|
|
|
-
|
|
|
- if ( target )
|
|
|
+
|
|
|
+ if ( target )
|
|
|
|
|
|
* Sign of x is positive. *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
- if ( xHead < 0x41dffffful )
|
|
|
+ if ( xHead < 0x41dffffful )
|
|
|
{
|
|
|
y = ( x + twoTo52 ) - twoTo52;
|
|
|
argument.dbl = y + doubleToLong;
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
|
|
-
|
|
|
- if ( xHead > 0x41dffffful )
|
|
|
+
|
|
|
+ if ( xHead > 0x41dffffful )
|
|
|
{
|
|
|
OldEnvironment.words.lo |= SET_INVALID;
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
|
return ( LONG_MAX );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
|
|
|
* x > 0.0 and may or may not be out of range of long. *
|
|
|
*******************************************************************************/
|
|
|
|
|
|
y = ( x + twoTo52 ) - twoTo52;
|
|
|
- if ( y > ( double ) LONG_MAX )
|
|
|
+ if ( y > ( double ) LONG_MAX )
|
|
|
{
|
|
|
OldEnvironment.words.lo |= SET_INVALID;
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
@@ -160,32 +160,32 @@ long int rinttol ( double x )
|
|
|
argument.dbl = y + doubleToLong;
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
|
|
|
* Sign of x is negative. *
|
|
|
*******************************************************************************/
|
|
|
- if ( xHead < 0x41e00000ul )
|
|
|
+ if ( xHead < 0x41e00000ul )
|
|
|
{
|
|
|
y = ( x - twoTo52 ) + twoTo52;
|
|
|
argument.dbl = y + doubleToLong;
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
|
|
-
|
|
|
- if ( xHead > 0x41e00000ul )
|
|
|
+
|
|
|
+ if ( xHead > 0x41e00000ul )
|
|
|
{
|
|
|
OldEnvironment.words.lo |= SET_INVALID;
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
|
return ( LONG_MIN );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
|
|
|
* x < 0.0 and may or may not be out of range of long. *
|
|
|
*******************************************************************************/
|
|
|
|
|
|
y = ( x - twoTo52 ) + twoTo52;
|
|
|
- if ( y < ( double ) LONG_MIN )
|
|
|
+ if ( y < ( double ) LONG_MIN )
|
|
|
{
|
|
|
OldEnvironment.words.lo |= SET_INVALID;
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
@@ -204,30 +204,30 @@ long int rinttol ( double x )
|
|
|
* return value is not equal to the operand. *
|
|
|
* *
|
|
|
*******************************************************************************/
|
|
|
-
|
|
|
+
|
|
|
double round ( double x )
|
|
|
- {
|
|
|
+ {
|
|
|
DblInHex argument, OldEnvironment;
|
|
|
register double y, z;
|
|
|
register unsigned long int xHead;
|
|
|
register long int target;
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = x;
|
|
|
xHead = argument.words.hi & 0x7fffffffUL;
|
|
|
target = ( argument.words.hi < signMask );
|
|
|
-
|
|
|
- if ( xHead < 0x43300000ul )
|
|
|
+
|
|
|
+ if ( xHead < 0x43300000ul )
|
|
|
|
|
|
* Is |x| < 2.0^52? *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
- if ( xHead < 0x3ff00000ul )
|
|
|
+ if ( xHead < 0x3ff00000ul )
|
|
|
|
|
|
* Is |x| < 1.0? *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
|
|
- if ( xHead < 0x3fe00000ul )
|
|
|
+ if ( xHead < 0x3fe00000ul )
|
|
|
|
|
|
* Is |x| < 0.5? *
|
|
|
*******************************************************************************/
|
|
@@ -235,7 +235,7 @@ double round ( double x )
|
|
|
if ( ( xHead | argument.words.lo ) != 0ul )
|
|
|
OldEnvironment.words.lo |= 0x02000000ul;
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
|
- if ( target )
|
|
|
+ if ( target )
|
|
|
return ( 0.0 );
|
|
|
else
|
|
|
return ( -0.0 );
|
|
@@ -253,7 +253,7 @@ double round ( double x )
|
|
|
|
|
|
* Is 1.0 < |x| < 2.0^52? *
|
|
|
*******************************************************************************/
|
|
|
- if ( target )
|
|
|
+ if ( target )
|
|
|
{
|
|
|
y = ( x + twoTo52 ) - twoTo52;
|
|
|
if ( y == x )
|
|
@@ -265,11 +265,11 @@ double round ( double x )
|
|
|
else
|
|
|
return ( y );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
|
|
|
* Is x < 0? *
|
|
|
*******************************************************************************/
|
|
|
- else
|
|
|
+ else
|
|
|
{
|
|
|
y = ( x - twoTo52 ) + twoTo52;
|
|
|
if ( y == x )
|
|
@@ -302,19 +302,19 @@ double round ( double x )
|
|
|
*******************************************************************************/
|
|
|
|
|
|
long int roundtol ( double x )
|
|
|
- {
|
|
|
+ {
|
|
|
register double y, z;
|
|
|
DblInHex argument, OldEnvironment;
|
|
|
register unsigned long int xhi;
|
|
|
register long int target;
|
|
|
const DblInHex kTZ = {{ 0x0, 0x1 }};
|
|
|
const DblInHex kUP = {{ 0x0, 0x2 }};
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = x;
|
|
|
xhi = argument.words.hi & 0x7ffffffful;
|
|
|
target = ( argument.words.hi < signMask );
|
|
|
-
|
|
|
- if ( xhi > 0x41e00000ul )
|
|
|
+
|
|
|
+ if ( xhi > 0x41e00000ul )
|
|
|
|
|
|
* Is x is out of long range or NaN? *
|
|
|
*******************************************************************************/
|
|
@@ -327,19 +327,19 @@ long int roundtol ( double x )
|
|
|
else
|
|
|
return ( LONG_MIN );
|
|
|
}
|
|
|
-
|
|
|
- if ( target )
|
|
|
+
|
|
|
+ if ( target )
|
|
|
|
|
|
* Is sign of x is "+"? *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
- if ( x < 2147483647.5 )
|
|
|
+ if ( x < 2147483647.5 )
|
|
|
|
|
|
* x is in the range of a long. *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
y = ( x + doubleToLong ) - doubleToLong;
|
|
|
- if ( y != x )
|
|
|
+ if ( y != x )
|
|
|
{
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
|
|
asm ("mtfsf 255,%0" : : "f" ( kTZ.dbl ));
|
|
@@ -348,7 +348,7 @@ long int roundtol ( double x )
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = y + doubleToLong;
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
@@ -363,13 +363,13 @@ long int roundtol ( double x )
|
|
|
|
|
|
* x < 0.0 and may or may not be out of the range of a long. *
|
|
|
*******************************************************************************/
|
|
|
- if ( x > -2147483648.5 )
|
|
|
+ if ( x > -2147483648.5 )
|
|
|
|
|
|
* x is in the range of a long. *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
y = ( x + doubleToLong ) - doubleToLong;
|
|
|
- if ( y != x )
|
|
|
+ if ( y != x )
|
|
|
{
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
|
|
asm ("mtfsf 255,%0" : : "f" ( kUP.dbl ));
|
|
@@ -378,7 +378,7 @@ long int roundtol ( double x )
|
|
|
asm ("mtfsf 255,%0" : : "f" ( OldEnvironment.dbl ));
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = y + doubleToLong;
|
|
|
return ( ( long ) argument.words.lo );
|
|
|
}
|
|
@@ -398,29 +398,29 @@ long int roundtol ( double x )
|
|
|
* inexact if an ordered return value is not equal to the operand. *
|
|
|
* *
|
|
|
*******************************************************************************/
|
|
|
-
|
|
|
+
|
|
|
double trunc ( double x )
|
|
|
- {
|
|
|
+ {
|
|
|
DblInHex argument,OldEnvironment;
|
|
|
register double y;
|
|
|
register unsigned long int xhi;
|
|
|
register long int target;
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = x;
|
|
|
xhi = argument.words.hi & 0x7fffffffUL;
|
|
|
target = ( argument.words.hi < signMask );
|
|
|
-
|
|
|
- if ( xhi < 0x43300000ul )
|
|
|
+
|
|
|
+ if ( xhi < 0x43300000ul )
|
|
|
|
|
|
* Is |x| < 2.0^53? *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
- if ( xhi < 0x3ff00000ul )
|
|
|
+ if ( xhi < 0x3ff00000ul )
|
|
|
|
|
|
* Is |x| < 1.0? *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
- if ( ( xhi | argument.words.lo ) != 0ul )
|
|
|
+ if ( ( xhi | argument.words.lo ) != 0ul )
|
|
|
{
|
|
|
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
|
|
|
OldEnvironment.words.lo |= 0x02000000ul;
|
|
@@ -434,7 +434,7 @@ double trunc ( double x )
|
|
|
|
|
|
* Is 1.0 < |x| < 2.0^52? *
|
|
|
*******************************************************************************/
|
|
|
- if ( target )
|
|
|
+ if ( target )
|
|
|
{
|
|
|
y = ( x + twoTo52 ) - twoTo52;
|
|
|
if ( y > x )
|
|
@@ -442,8 +442,8 @@ double trunc ( double x )
|
|
|
else
|
|
|
return ( y );
|
|
|
}
|
|
|
-
|
|
|
- else
|
|
|
+
|
|
|
+ else
|
|
|
{
|
|
|
y = ( x - twoTo52 ) + twoTo52;
|
|
|
if ( y < x )
|
|
@@ -470,7 +470,7 @@ double trunc ( double x )
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
|
-* modf is the double implementation. *
|
|
|
+* modf is the double implementation. *
|
|
|
*******************************************************************************/
|
|
|
|
|
|
double modf ( double x, double *iptr )
|
|
@@ -478,19 +478,19 @@ double modf ( double x, double *iptr )
|
|
|
register double OldEnvironment, xtrunc;
|
|
|
register unsigned long int xHead, signBit;
|
|
|
DblInHex argument;
|
|
|
-
|
|
|
+
|
|
|
argument.dbl = x;
|
|
|
xHead = argument.words.hi & 0x7ffffffful;
|
|
|
signBit = ( argument.words.hi & 0x80000000ul );
|
|
|
if (xHead == 0x7ff81fe0)
|
|
|
signBit = signBit | 0;
|
|
|
-
|
|
|
- if ( xHead < 0x43300000ul )
|
|
|
+
|
|
|
+ if ( xHead < 0x43300000ul )
|
|
|
|
|
|
* Is |x| < 2.0^53? *
|
|
|
*******************************************************************************/
|
|
|
{
|
|
|
- if ( xHead < 0x3ff00000ul )
|
|
|
+ if ( xHead < 0x3ff00000ul )
|
|
|
|
|
|
* Is |x| < 1.0? *
|
|
|
*******************************************************************************/
|
|
@@ -515,18 +515,18 @@ double modf ( double x, double *iptr )
|
|
|
*iptr = xtrunc;
|
|
|
if ( x != xtrunc )
|
|
|
return ( x - xtrunc );
|
|
|
- else
|
|
|
+ else
|
|
|
{
|
|
|
argument.words.hi = signBit;
|
|
|
argument.words.lo = 0ul;
|
|
|
return ( argument.dbl );
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
*iptr = x;
|
|
|
if ( x != x )
|
|
|
return x;
|
|
|
- else
|
|
|
+ else
|
|
|
{
|
|
|
argument.words.hi = signBit;
|
|
|
argument.words.lo = 0ul;
|