From 26d7ea91124a9405dff7755a78cfb6232dd15d80 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Sat, 24 Nov 2001 03:46:25 +0000 Subject: Move powerpc specific optimizations (courtesy of apple) to powerpc subdir. Put together a theoretical framework for adding arch specific optimizations. Havn't tried this yet but it looks correct... -Erik --- libm/Makefile | 29 ++- libm/ceilfloor.c | 179 ------------- libm/frexpldexp.c | 73 ------ libm/logb.c | 104 -------- libm/powerpc/Makefile | 60 +++++ libm/powerpc/ceilfloor.c | 174 +++++++++++++ libm/powerpc/frexpldexp.c | 72 ++++++ libm/powerpc/logb.c | 103 ++++++++ libm/powerpc/rndint.c | 620 +++++++++++++++++++++++++++++++++++++++++++++ libm/powerpc/scalb.c | 85 +++++++ libm/powerpc/sign.c | 56 ++++ libm/rndint.c | 632 ---------------------------------------------- libm/s_ceil.c | 3 +- libm/s_copysign.c | 3 +- libm/s_floor.c | 2 - libm/s_frexp.c | 2 - libm/s_ldexp.c | 2 - libm/s_logb.c | 2 - libm/s_modf.c | 2 - libm/s_rint.c | 2 - libm/scalb.c | 87 ------- libm/sign.c | 58 ----- libm/w_scalb.c | 2 - 23 files changed, 1195 insertions(+), 1157 deletions(-) delete mode 100644 libm/ceilfloor.c delete mode 100644 libm/frexpldexp.c delete mode 100644 libm/logb.c create mode 100644 libm/powerpc/Makefile create mode 100644 libm/powerpc/ceilfloor.c create mode 100644 libm/powerpc/frexpldexp.c create mode 100644 libm/powerpc/logb.c create mode 100644 libm/powerpc/rndint.c create mode 100644 libm/powerpc/scalb.c create mode 100644 libm/powerpc/sign.c delete mode 100644 libm/rndint.c delete mode 100644 libm/scalb.c delete mode 100644 libm/sign.c diff --git a/libm/Makefile b/libm/Makefile index c82ca3f25..e9c7c807d 100644 --- a/libm/Makefile +++ b/libm/Makefile @@ -22,6 +22,14 @@ TOPDIR=../ include $(TOPDIR)Rules.mak +ifeq ($(TARGET_ARCH),$(wildcard $(TARGET_ARCH))) +DIRS = $(TARGET_ARCH) +else +DIRS = +endif +ALL_SUBDIRS = powerpc + + LIBM=libm.a LIBM_SHARED=libm.so LIBM_SHARED_FULLNAME=libm-$(MAJOR_VERSION).$(MINOR_VERSION).so @@ -43,8 +51,7 @@ CSRC = e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c\ w_cosh.c w_drem.c w_exp.c w_fmod.c w_gamma.c w_gamma_r.c\ w_hypot.c w_j0.c w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c\ w_log.c w_log10.c w_pow.c w_remainder.c w_scalb.c w_sinh.c\ - w_sqrt.c ceilfloor.c fpmacros.c frexpldexp.c logb.c rndint.c\ - scalb.c sign.c + w_sqrt.c fpmacros.c else CSRC = w_acos.c w_asin.c s_atan.c w_atan2.c s_ceil.c s_cos.c \ w_cosh.c w_exp.c s_expm1.c s_fabs.c s_floor.c w_fmod.c \ @@ -59,9 +66,9 @@ OBJS=$(COBJS) ifneq ($(strip $(HAS_FLOATING_POINT)),true) -all: clean +all: clean subdirs else -all: $(OBJS) $(COBJS1) $(LIBM) +all: $(OBJS) $(LIBM) subdirs endif $(LIBM): ar-target @@ -90,11 +97,21 @@ $(COBJS): %.o : %.c $(STRIPTOOL) -x -R .note -R .comment $*.o $(OBJ): Makefile -$(COBJS1): Makefile tags: ctags -R -clean: +clean: subdirs_clean rm -f *.[oa] *~ core $(LIBM_SHARED)* $(LIBM_SHARED_FULLNAME)* +subdirs: $(patsubst %, _dir_%, $(DIRS)) +subdirs_clean: $(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) + +$(patsubst %, _dir_%, $(DIRS)) : dummy + $(MAKE) -C $(patsubst _dir_%, %, $@) + +$(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) : dummy + $(MAKE) -C $(patsubst _dirclean_%, %, $@) clean + +.PHONY: dummy + diff --git a/libm/ceilfloor.c b/libm/ceilfloor.c deleted file mode 100644 index 9607435c3..000000000 --- a/libm/ceilfloor.c +++ /dev/null @@ -1,179 +0,0 @@ -#if defined(__ppc__) -/******************************************************************************* -* * -* File ceilfloor.c, * -* Function ceil(x) and floor(x), * -* Implementation of ceil and floor for the PowerPC. * -* * -* Copyright © 1991 Apple Computer, Inc. All rights reserved. * -* * -* Written by Ali Sazegari, started on November 1991, * -* * -* based on math.h, library code for Macintoshes with a 68881/68882 * -* by Jim Thomas. * -* * -* W A R N I N G: This routine expects a 64 bit double model. * -* * -* December 03 1992: first rs6000 port. * -* July 14 1993: comment changes and addition of #pragma fenv_access. * -* May 06 1997: port of the ibm/taligent ceil and floor routines. * -* April 11 2001: first port to os x using gcc. * -* June 13 2001: replaced __setflm with in-line assembly * -* * -*******************************************************************************/ - -#if !defined(__ppc__) -#define asm(x) -#endif - -static const double twoTo52 = 4503599627370496.0; -static const unsigned long signMask = 0x80000000ul; - -typedef union - { - struct { -#if defined(__BIG_ENDIAN__) - unsigned long int hi; - unsigned long int lo; -#else - unsigned long int lo; - unsigned long int hi; -#endif - } words; - double dbl; - } DblInHex; - -/******************************************************************************* -* Functions needed for the computation. * -*******************************************************************************/ - -/******************************************************************************* -* Ceil(x) returns the smallest integer not less than x. * -*******************************************************************************/ - -double ceil ( double x ) - { - DblInHex xInHex,OldEnvironment; - register double y; - register unsigned long int xhi; - register int target; - - xInHex.dbl = x; - xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x| - target = ( xInHex.words.hi < signMask ); - - if ( xhi < 0x43300000ul ) -/******************************************************************************* -* Is |x| < 2.0^52? * -*******************************************************************************/ - { - if ( xhi < 0x3ff00000ul ) -/******************************************************************************* -* Is |x| < 1.0? * -*******************************************************************************/ - { - if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case - return ( x ); - else - { // inexact case - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); - OldEnvironment.words.lo |= 0x02000000ul; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - if ( target ) - return ( 1.0 ); - else - return ( -0.0 ); - } - } -/******************************************************************************* -* Is 1.0 < |x| < 2.0^52? * -*******************************************************************************/ - if ( target ) - { - y = ( x + twoTo52 ) - twoTo52; // round at binary pt. - if ( y < x ) - return ( y + 1.0 ); - else - return ( y ); - } - - else - { - y = ( x - twoTo52 ) + twoTo52; // round at binary pt. - if ( y < x ) - return ( y + 1.0 ); - else - return ( y ); - } - } -/******************************************************************************* -* |x| >= 2.0^52 or x is a NaN. * -*******************************************************************************/ - return ( x ); - } - -/******************************************************************************* -* Floor(x) returns the largest integer not greater than x. * -*******************************************************************************/ - -double floor ( double x ) - { - DblInHex xInHex,OldEnvironment; - register double y; - register unsigned long int xhi; - register long int target; - - xInHex.dbl = x; - xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x| - target = ( xInHex.words.hi < signMask ); - - if ( xhi < 0x43300000ul ) -/******************************************************************************* -* Is |x| < 2.0^52? * -*******************************************************************************/ - { - if ( xhi < 0x3ff00000ul ) -/******************************************************************************* -* Is |x| < 1.0? * -*******************************************************************************/ - { - if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case - return ( x ); - else - { // inexact case - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); - OldEnvironment.words.lo |= 0x02000000ul; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - if ( target ) - return ( 0.0 ); - else - return ( -1.0 ); - } - } -/******************************************************************************* -* Is 1.0 < |x| < 2.0^52? * -*******************************************************************************/ - if ( target ) - { - y = ( x + twoTo52 ) - twoTo52; // round at binary pt. - if ( y > x ) - return ( y - 1.0 ); - else - return ( y ); - } - - else - { - y = ( x - twoTo52 ) + twoTo52; // round at binary pt. - if ( y > x ) - return ( y - 1.0 ); - else - return ( y ); - } - } -/******************************************************************************* -* |x| >= 2.0^52 or x is a NaN. * -*******************************************************************************/ - return ( x ); - } -#endif /* __ppc__ */ diff --git a/libm/frexpldexp.c b/libm/frexpldexp.c deleted file mode 100644 index dbb6fcc64..000000000 --- a/libm/frexpldexp.c +++ /dev/null @@ -1,73 +0,0 @@ -#if defined(__ppc__) -/******************************************************************************* -* * -* File frexpldexp.c, * -* Functions frexp(x) and ldexp(x), * -* Implementation of frexp and ldexp functions for the PowerPC. * -* * -* Copyright © 1991 Apple Computer, Inc. All rights reserved. * -* * -* Written by Ali Sazegari, started on January 1991, * -* * -* W A R N I N G: This routine expects a 64 bit double model. * -* * -* December03 1992: first rs6000 implementation. * -* October 05 1993: added special cases for NaN and ° in frexp. * -* May 27 1997: improved the performance of frexp by eliminating the * -* switch statement. * -* June 13 2001: (ram) rewrote frexp to eliminate calls to scalb and * -* logb. * -* * -*******************************************************************************/ - -#include -#include - -static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ - -typedef union - { - struct { -#if defined(__BIG_ENDIAN__) - unsigned long int hi; - unsigned long int lo; -#else - unsigned long int lo; - unsigned long int hi; -#endif - } words; - double dbl; - } DblInHex; - -double ldexp ( double value, int exp ) - { - if ( exp > SHRT_MAX ) - exp = SHRT_MAX; - else if ( exp < -SHRT_MAX ) - exp = -SHRT_MAX; - return scalb ( value, exp ); - } - -double frexp ( double value, int *eptr ) - { - DblInHex argument; - unsigned long int valueHead; - - argument.dbl = value; - valueHead = argument.words.hi & 0x7fffffffUL; // valueHead <- |x| - - *eptr = 0; - if ( valueHead >= 0x7ff00000 || ( valueHead | argument.words.lo ) == 0 ) - return value; // 0, inf, or NaN - - if ( valueHead < 0x00100000 ) - { // denorm - argument.dbl = two54 * value; - valueHead = argument.words.hi &0x7fffffff; - *eptr = -54; - } - *eptr += ( valueHead >> 20 ) - 1022; - argument.words.hi = ( argument.words.hi & 0x800fffff ) | 0x3fe00000; - return argument.dbl; - } -#endif /* __ppc__ */ diff --git a/libm/logb.c b/libm/logb.c deleted file mode 100644 index da2a27d72..000000000 --- a/libm/logb.c +++ /dev/null @@ -1,104 +0,0 @@ -#if defined(__ppc__) -/******************************************************************************* -* * -* File logb.c, * -* Functions logb. * -* Implementation of logb for the PowerPC. * -* * -* Copyright © 1991 Apple Computer, Inc. All rights reserved. * -* * -* Written by Ali Sazegari, started on June 1991, * -* * -* August 26 1991: removed CFront Version 1.1d17 warnings. * -* August 27 1991: no errors reported by the test suite. * -* November 11 1991: changed CLASSEXTENDED to the macro CLASSIFY and * -* + or - infinity to constants. * -* November 18 1991: changed the macro CLASSIFY to CLASSEXTENDEDint to * -* improve performance. * -* February 07 1992: changed bit operations to macros ( object size is * -* unchanged ). * -* September24 1992: took the "#include support.h" out. * -* December 03 1992: first rs/6000 port. * -* August 30 1992: set the divide by zero for the zero argument case. * -* October 05 1993: corrected the environment. * -* October 17 1994: replaced all environmental functions with __setflm. * -* May 28 1997: made speed improvements. * -* April 30 2001: forst mac os x port using gcc. * -* * -******************************************************************************** -* The C math library offers a similar function called "frexp". It is * -* different in details from logb, but similar in spirit. This current * -* implementation of logb follows the recommendation in IEEE Standard 854 * -* which is different in its handling of denormalized numbers from the IEEE * -* Standard 754. * -*******************************************************************************/ - -typedef union - { - struct { -#if defined(__BIG_ENDIAN__) - unsigned long int hi; - unsigned long int lo; -#else - unsigned long int lo; - unsigned long int hi; -#endif - } words; - double dbl; - } DblInHex; - -static const double twoTo52 = 4.50359962737049600e15; // 0x1p52 -static const double klTod = 4503601774854144.0; // 0x1.000008p52 -static const unsigned long int signMask = 0x80000000ul; -static const DblInHex minusInf = {{ 0xFFF00000, 0x00000000 }}; - - -/******************************************************************************* -******************************************************************************** -* L O G B * -******************************************************************************** -*******************************************************************************/ - -double logb ( double x ) - { - DblInHex xInHex; - long int shiftedExp; - - xInHex.dbl = x; - shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20; - - if ( shiftedExp == 2047 ) - { // NaN or INF - if ( ( ( xInHex.words.hi & signMask ) == 0 ) || ( x != x ) ) - return x; // NaN or +INF return x - else - return -x; // -INF returns +INF - } - - if ( shiftedExp != 0 ) // normal number - shiftedExp -= 1023; // unbias exponent - - else if ( x == 0.0 ) - { // zero - xInHex.words.hi = 0x0UL; // return -infinity - return ( minusInf.dbl ); - } - - else - { // subnormal number - xInHex.dbl *= twoTo52; // scale up - shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20; - shiftedExp -= 1075; // unbias exponent - } - - if ( shiftedExp == 0 ) // zero result - return ( 0.0 ); - - else - { // nonzero result - xInHex.dbl = klTod; - xInHex.words.lo += shiftedExp; - return ( xInHex.dbl - klTod ); - } - } -#endif /* __ppc__ */ diff --git a/libm/powerpc/Makefile b/libm/powerpc/Makefile new file mode 100644 index 000000000..7464ee0a8 --- /dev/null +++ b/libm/powerpc/Makefile @@ -0,0 +1,60 @@ +# Makefile for uClibc's math library +# Copyright (C) 2001 by Lineo, inc. +# +# This math library is derived primarily from the Cephes Math Library, +# copyright by Stephen L. Moshier +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR=../../ +include $(TOPDIR)Rules.mak + +LIBM=../libm.a +TARGET_CC= $(TOPDIR)extra/gcc-uClibc/$(TARGET_ARCH)-uclibc-gcc +TARGET_CFLAGS+=-D_IEEE_LIBM -D_ISOC99_SOURCE -D_SVID_SOURCE + +ifeq ($(strip $(DO_C99_MATH)),true) +CSRC = ceilfloor.c frexpldexp.c logb.c rndint.c scalb.c sign.c +else +CSRC = +endif +COBJS=$(patsubst %.c,%.o, $(CSRC)) +OBJS=$(COBJS) + + +ifneq ($(strip $(HAS_FLOATING_POINT)),true) +all: clean +else +all: $(OBJS) $(LIBM) +endif + +$(LIBM): ar-target + +ar-target: $(OBJS) + $(AR) $(ARFLAGS) $(LIBM) $(OBJS) + +$(COBJS): %.o : %.c + $(TARGET_CC) $(TARGET_CFLAGS) -c $< -o $@ + $(STRIPTOOL) -x -R .note -R .comment $*.o + +$(OBJ): Makefile + +tags: + ctags -R + +clean: + rm -f *.[oa] *~ core $(LIBM_SHARED)* $(LIBM_SHARED_FULLNAME)* + diff --git a/libm/powerpc/ceilfloor.c b/libm/powerpc/ceilfloor.c new file mode 100644 index 000000000..d5947ab50 --- /dev/null +++ b/libm/powerpc/ceilfloor.c @@ -0,0 +1,174 @@ +/******************************************************************************* +* * +* File ceilfloor.c, * +* Function ceil(x) and floor(x), * +* Implementation of ceil and floor for the PowerPC. * +* * +* Copyright © 1991 Apple Computer, Inc. All rights reserved. * +* * +* Written by Ali Sazegari, started on November 1991, * +* * +* based on math.h, library code for Macintoshes with a 68881/68882 * +* by Jim Thomas. * +* * +* W A R N I N G: This routine expects a 64 bit double model. * +* * +* December 03 1992: first rs6000 port. * +* July 14 1993: comment changes and addition of #pragma fenv_access. * +* May 06 1997: port of the ibm/taligent ceil and floor routines. * +* April 11 2001: first port to os x using gcc. * +* June 13 2001: replaced __setflm with in-line assembly * +* * +*******************************************************************************/ + +static const double twoTo52 = 4503599627370496.0; +static const unsigned long signMask = 0x80000000ul; + +typedef union + { + struct { +#if defined(__BIG_ENDIAN__) + unsigned long int hi; + unsigned long int lo; +#else + unsigned long int lo; + unsigned long int hi; +#endif + } words; + double dbl; + } DblInHex; + +/******************************************************************************* +* Functions needed for the computation. * +*******************************************************************************/ + +/******************************************************************************* +* Ceil(x) returns the smallest integer not less than x. * +*******************************************************************************/ + +double ceil ( double x ) + { + DblInHex xInHex,OldEnvironment; + register double y; + register unsigned long int xhi; + register int target; + + xInHex.dbl = x; + xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x| + target = ( xInHex.words.hi < signMask ); + + if ( xhi < 0x43300000ul ) +/******************************************************************************* +* Is |x| < 2.0^52? * +*******************************************************************************/ + { + if ( xhi < 0x3ff00000ul ) +/******************************************************************************* +* Is |x| < 1.0? * +*******************************************************************************/ + { + if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case + return ( x ); + else + { // inexact case + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); + OldEnvironment.words.lo |= 0x02000000ul; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + if ( target ) + return ( 1.0 ); + else + return ( -0.0 ); + } + } +/******************************************************************************* +* Is 1.0 < |x| < 2.0^52? * +*******************************************************************************/ + if ( target ) + { + y = ( x + twoTo52 ) - twoTo52; // round at binary pt. + if ( y < x ) + return ( y + 1.0 ); + else + return ( y ); + } + + else + { + y = ( x - twoTo52 ) + twoTo52; // round at binary pt. + if ( y < x ) + return ( y + 1.0 ); + else + return ( y ); + } + } +/******************************************************************************* +* |x| >= 2.0^52 or x is a NaN. * +*******************************************************************************/ + return ( x ); + } + +/******************************************************************************* +* Floor(x) returns the largest integer not greater than x. * +*******************************************************************************/ + +double floor ( double x ) + { + DblInHex xInHex,OldEnvironment; + register double y; + register unsigned long int xhi; + register long int target; + + xInHex.dbl = x; + xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x| + target = ( xInHex.words.hi < signMask ); + + if ( xhi < 0x43300000ul ) +/******************************************************************************* +* Is |x| < 2.0^52? * +*******************************************************************************/ + { + if ( xhi < 0x3ff00000ul ) +/******************************************************************************* +* Is |x| < 1.0? * +*******************************************************************************/ + { + if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case + return ( x ); + else + { // inexact case + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); + OldEnvironment.words.lo |= 0x02000000ul; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + if ( target ) + return ( 0.0 ); + else + return ( -1.0 ); + } + } +/******************************************************************************* +* Is 1.0 < |x| < 2.0^52? * +*******************************************************************************/ + if ( target ) + { + y = ( x + twoTo52 ) - twoTo52; // round at binary pt. + if ( y > x ) + return ( y - 1.0 ); + else + return ( y ); + } + + else + { + y = ( x - twoTo52 ) + twoTo52; // round at binary pt. + if ( y > x ) + return ( y - 1.0 ); + else + return ( y ); + } + } +/******************************************************************************* +* |x| >= 2.0^52 or x is a NaN. * +*******************************************************************************/ + return ( x ); + } + diff --git a/libm/powerpc/frexpldexp.c b/libm/powerpc/frexpldexp.c new file mode 100644 index 000000000..6b759f91b --- /dev/null +++ b/libm/powerpc/frexpldexp.c @@ -0,0 +1,72 @@ +/******************************************************************************* +* * +* File frexpldexp.c, * +* Functions frexp(x) and ldexp(x), * +* Implementation of frexp and ldexp functions for the PowerPC. * +* * +* Copyright © 1991 Apple Computer, Inc. All rights reserved. * +* * +* Written by Ali Sazegari, started on January 1991, * +* * +* W A R N I N G: This routine expects a 64 bit double model. * +* * +* December03 1992: first rs6000 implementation. * +* October 05 1993: added special cases for NaN and ° in frexp. * +* May 27 1997: improved the performance of frexp by eliminating the * +* switch statement. * +* June 13 2001: (ram) rewrote frexp to eliminate calls to scalb and * +* logb. * +* * +*******************************************************************************/ + +#include +#include + +static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ + +typedef union + { + struct { +#if defined(__BIG_ENDIAN__) + unsigned long int hi; + unsigned long int lo; +#else + unsigned long int lo; + unsigned long int hi; +#endif + } words; + double dbl; + } DblInHex; + +double ldexp ( double value, int exp ) + { + if ( exp > SHRT_MAX ) + exp = SHRT_MAX; + else if ( exp < -SHRT_MAX ) + exp = -SHRT_MAX; + return scalb ( value, exp ); + } + +double frexp ( double value, int *eptr ) + { + DblInHex argument; + unsigned long int valueHead; + + argument.dbl = value; + valueHead = argument.words.hi & 0x7fffffffUL; // valueHead <- |x| + + *eptr = 0; + if ( valueHead >= 0x7ff00000 || ( valueHead | argument.words.lo ) == 0 ) + return value; // 0, inf, or NaN + + if ( valueHead < 0x00100000 ) + { // denorm + argument.dbl = two54 * value; + valueHead = argument.words.hi &0x7fffffff; + *eptr = -54; + } + *eptr += ( valueHead >> 20 ) - 1022; + argument.words.hi = ( argument.words.hi & 0x800fffff ) | 0x3fe00000; + return argument.dbl; + } + diff --git a/libm/powerpc/logb.c b/libm/powerpc/logb.c new file mode 100644 index 000000000..3a410ba5c --- /dev/null +++ b/libm/powerpc/logb.c @@ -0,0 +1,103 @@ +/******************************************************************************* +* * +* File logb.c, * +* Functions logb. * +* Implementation of logb for the PowerPC. * +* * +* Copyright © 1991 Apple Computer, Inc. All rights reserved. * +* * +* Written by Ali Sazegari, started on June 1991, * +* * +* August 26 1991: removed CFront Version 1.1d17 warnings. * +* August 27 1991: no errors reported by the test suite. * +* November 11 1991: changed CLASSEXTENDED to the macro CLASSIFY and * +* + or - infinity to constants. * +* November 18 1991: changed the macro CLASSIFY to CLASSEXTENDEDint to * +* improve performance. * +* February 07 1992: changed bit operations to macros ( object size is * +* unchanged ). * +* September24 1992: took the "#include support.h" out. * +* December 03 1992: first rs/6000 port. * +* August 30 1992: set the divide by zero for the zero argument case. * +* October 05 1993: corrected the environment. * +* October 17 1994: replaced all environmental functions with __setflm. * +* May 28 1997: made speed improvements. * +* April 30 2001: forst mac os x port using gcc. * +* * +******************************************************************************** +* The C math library offers a similar function called "frexp". It is * +* different in details from logb, but similar in spirit. This current * +* implementation of logb follows the recommendation in IEEE Standard 854 * +* which is different in its handling of denormalized numbers from the IEEE * +* Standard 754. * +*******************************************************************************/ + +typedef union + { + struct { +#if defined(__BIG_ENDIAN__) + unsigned long int hi; + unsigned long int lo; +#else + unsigned long int lo; + unsigned long int hi; +#endif + } words; + double dbl; + } DblInHex; + +static const double twoTo52 = 4.50359962737049600e15; // 0x1p52 +static const double klTod = 4503601774854144.0; // 0x1.000008p52 +static const unsigned long int signMask = 0x80000000ul; +static const DblInHex minusInf = {{ 0xFFF00000, 0x00000000 }}; + + +/******************************************************************************* +******************************************************************************** +* L O G B * +******************************************************************************** +*******************************************************************************/ + +double logb ( double x ) + { + DblInHex xInHex; + long int shiftedExp; + + xInHex.dbl = x; + shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20; + + if ( shiftedExp == 2047 ) + { // NaN or INF + if ( ( ( xInHex.words.hi & signMask ) == 0 ) || ( x != x ) ) + return x; // NaN or +INF return x + else + return -x; // -INF returns +INF + } + + if ( shiftedExp != 0 ) // normal number + shiftedExp -= 1023; // unbias exponent + + else if ( x == 0.0 ) + { // zero + xInHex.words.hi = 0x0UL; // return -infinity + return ( minusInf.dbl ); + } + + else + { // subnormal number + xInHex.dbl *= twoTo52; // scale up + shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20; + shiftedExp -= 1075; // unbias exponent + } + + if ( shiftedExp == 0 ) // zero result + return ( 0.0 ); + + else + { // nonzero result + xInHex.dbl = klTod; + xInHex.words.lo += shiftedExp; + return ( xInHex.dbl - klTod ); + } + } + diff --git a/libm/powerpc/rndint.c b/libm/powerpc/rndint.c new file mode 100644 index 000000000..1b7a9ec81 --- /dev/null +++ b/libm/powerpc/rndint.c @@ -0,0 +1,620 @@ +/******************************************************************************* +** File: rndint.c +** +** Contains: C source code for implementations of floating-point +** functions which round to integral value or format, as +** defined in header . 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 +** 03 Mar 01 ali first port to os x using gcc, added the crucial __setflm +** definition. +** 1. removed double_t, put in double for now. +** 2. removed iclass from nearbyint. +** 3. removed wrong comments intrunc. +** 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, +** rint is more elegant, but slower by %30 than the taligent one. +** 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c +** 15 Sep 94 ali Major overhaul and performance improvements of all functions. +** 20 Jul 94 PAF New faster version +** 16 Jul 93 ali Added the modfl function. +** 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 +** separate file. +** 15 Dec 92 JPO Added __itrunc implementation and modified +** rinttol to include conversion from double +** to long int format. Modified roundtol to +** call __itrunc. +** 10 Dec 92 JPO Added modf (double) implementation. +** 04 Dec 92 JPO First created. +** +*******************************************************************************/ + +#include +#include + +#define SET_INVALID 0x01000000UL + +typedef union + { + struct { +#if defined(__BIG_ENDIAN__) + unsigned long int hi; + unsigned long int lo; +#else + unsigned long int lo; + unsigned long int hi; +#endif + } words; + double dbl; + } DblInHex; + +static const unsigned long int signMask = 0x80000000ul; +static const double twoTo52 = 4503599627370496.0; +static const double doubleToLong = 4503603922337792.0; // 2^52 +static const DblInHex Huge = {{ 0x7FF00000, 0x00000000 }}; +static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }}; + +/******************************************************************************* +* * +* The function rint rounds its double argument to integral value * +* according to the current rounding direction and returns the result in * +* double format. This function signals inexact if an ordered return * +* value is not equal to the operand. * +* * +******************************************************************************** +* * +* This function calls: fabs. * +* * +*******************************************************************************/ + +/******************************************************************************* +* First, an elegant implementation. * +******************************************************************************** +* +*double rint ( double x ) +* { +* double y; +* +* y = twoTo52.fval; +* +* if ( fabs ( x ) >= y ) // huge case is exact +* return x; +* if ( x < 0 ) y = -y; // negative case +* y = ( x + y ) - y; // force rounding +* if ( y == 0.0 ) // zero results mirror sign of x +* y = copysign ( y, x ); +* return ( y ); +* } +******************************************************************************** +* Now a bit twidling version that is about %30 faster. * +*******************************************************************************/ + +double rint ( double x ) + { + DblInHex argument; + register double y; + unsigned long int xHead; + register long int target; + + argument.dbl = x; + xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x| + target = ( argument.words.hi < signMask ); // flags positive sign + + if ( xHead < 0x43300000ul ) +/******************************************************************************* +* Is |x| < 2.0^52? * +*******************************************************************************/ + { + if ( xHead < 0x3ff00000ul ) +/******************************************************************************* +* Is |x| < 1.0? * +*******************************************************************************/ + { + if ( target ) + y = ( x + twoTo52 ) - twoTo52; // round at binary point + else + y = ( x - twoTo52 ) + twoTo52; // round at binary point + if ( y == 0.0 ) + { // fix sign of zero result + if ( target ) + return ( 0.0 ); + else + return ( -0.0 ); + } + return y; + } + +/******************************************************************************* +* Is 1.0 < |x| < 2.0^52? * +*******************************************************************************/ + + if ( target ) + return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt. + else + return ( ( x - twoTo52 ) + twoTo52 ); + } + +/******************************************************************************* +* |x| >= 2.0^52 or x is a NaN. * +*******************************************************************************/ + return ( x ); + } + +/******************************************************************************* +* * +* The function nearbyint rounds its double argument to integral value * +* according to the current rounding direction and returns the result in * +* double format. This function does not signal inexact. * +* * +******************************************************************************** +* * +* This function calls fabs and copysign. * +* * +*******************************************************************************/ + +double nearbyint ( double x ) + { + double y; + double OldEnvironment; + + y = twoTo52; + + asm ("mffs %0" : "=f" (OldEnvironment)); /* get the environement */ + + if ( fabs ( x ) >= y ) /* huge case is exact */ + return x; + if ( x < 0 ) y = -y; /* negative case */ + y = ( x + y ) - y; /* force rounding */ + if ( y == 0.0 ) /* zero results mirror sign of x */ + y = copysign ( y, x ); +// restore old flags + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment )); + return ( y ); + } + +/******************************************************************************* +* * +* The function rinttol converts its double argument to integral value * +* according to the current rounding direction and returns the result in * +* long int format. This conversion signals invalid if the argument is a * +* NaN or the rounded intermediate result is out of range of the * +* destination long int format, and it delivers an unspecified result in * +* this case. This function signals inexact if the rounded result is * +* within range of the long int format but unequal to the operand. * +* * +*******************************************************************************/ + +long int rinttol ( double x ) + { + register double y; + DblInHex argument, OldEnvironment; + unsigned long int xHead; + register long int target; + + argument.dbl = x; + target = ( argument.words.hi < signMask ); // flag positive sign + xHead = argument.words.hi & 0x7ffffffful; // high 32 bits of x + + if ( target ) +/******************************************************************************* +* Sign of x is positive. * +*******************************************************************************/ + { + if ( xHead < 0x41dffffful ) + { // x is safely in long range + y = ( x + twoTo52 ) - twoTo52; // round at binary point + argument.dbl = y + doubleToLong; // force result into argument.words.lo + return ( ( long ) argument.words.lo ); + } + + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment + + if ( xHead > 0x41dffffful ) + { // x is safely out of long range + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( LONG_MAX ); + } + +/******************************************************************************* +* x > 0.0 and may or may not be out of range of long. * +*******************************************************************************/ + + y = ( x + twoTo52 ) - twoTo52; // do rounding + if ( y > ( double ) LONG_MAX ) + { // out of range of long + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( LONG_MAX ); + } + argument.dbl = y + doubleToLong; // in range + return ( ( long ) argument.words.lo ); // return result & flags + } + +/******************************************************************************* +* Sign of x is negative. * +*******************************************************************************/ + if ( xHead < 0x41e00000ul ) + { // x is safely in long range + y = ( x - twoTo52 ) + twoTo52; + argument.dbl = y + doubleToLong; + return ( ( long ) argument.words.lo ); + } + + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment + + if ( xHead > 0x41e00000ul ) + { // x is safely out of long range + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( LONG_MIN ); + } + +/******************************************************************************* +* x < 0.0 and may or may not be out of range of long. * +*******************************************************************************/ + + y = ( x - twoTo52 ) + twoTo52; // do rounding + if ( y < ( double ) LONG_MIN ) + { // out of range of long + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( LONG_MIN ); + } + argument.dbl = y + doubleToLong; // in range + return ( ( long ) argument.words.lo ); // return result & flags + } + +/******************************************************************************* +* * +* The function round rounds its double argument to integral value * +* according to the "add half to the magnitude and truncate" rounding of * +* Pascal's Round function and FORTRAN's ANINT function and returns the * +* result in double format. This function signals inexact if an ordered * +* 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; // xHead <- high half of |x| + target = ( argument.words.hi < signMask ); // flag positive sign + + if ( xHead < 0x43300000ul ) +/******************************************************************************* +* Is |x| < 2.0^52? * +*******************************************************************************/ + { + if ( xHead < 0x3ff00000ul ) +/******************************************************************************* +* Is |x| < 1.0? * +*******************************************************************************/ + { + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment + if ( xHead < 0x3fe00000ul ) +/******************************************************************************* +* Is |x| < 0.5? * +*******************************************************************************/ + { + if ( ( xHead | argument.words.lo ) != 0ul ) + OldEnvironment.words.lo |= 0x02000000ul; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + if ( target ) + return ( 0.0 ); + else + return ( -0.0 ); + } +/******************************************************************************* +* Is 0.5 ² |x| < 1.0? * +*******************************************************************************/ + OldEnvironment.words.lo |= 0x02000000ul; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + if ( target ) + return ( 1.0 ); + else + return ( -1.0 ); + } +/******************************************************************************* +* Is 1.0 < |x| < 2.0^52? * +*******************************************************************************/ + if ( target ) + { // positive x + y = ( x + twoTo52 ) - twoTo52; // round at binary point + if ( y == x ) // exact case + return ( x ); + z = x + 0.5; // inexact case + y = ( z + twoTo52 ) - twoTo52; // round at binary point + if ( y > z ) + return ( y - 1.0 ); + else + return ( y ); + } + +/******************************************************************************* +* Is x < 0? * +*******************************************************************************/ + else + { + y = ( x - twoTo52 ) + twoTo52; // round at binary point + if ( y == x ) + return ( x ); + z = x - 0.5; + y = ( z - twoTo52 ) + twoTo52; // round at binary point + if ( y < z ) + return ( y + 1.0 ); + else + return ( y ); + } + } +/******************************************************************************* +* |x| >= 2.0^52 or x is a NaN. * +*******************************************************************************/ + return ( x ); + } + +/******************************************************************************* +* * +* The function roundtol converts its double argument to integral format * +* according to the "add half to the magnitude and chop" rounding mode of * +* Pascal's Round function and FORTRAN's NINT function. This conversion * +* signals invalid if the argument is a NaN or the rounded intermediate * +* result is out of range of the destination long int format, and it * +* delivers an unspecified result in this case. This function signals * +* inexact if the rounded result is within range of the long int format but * +* unequal to the operand. * +* * +*******************************************************************************/ + +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; // high 32 bits of x + target = ( argument.words.hi < signMask ); // flag positive sign + + if ( xhi > 0x41e00000ul ) +/******************************************************************************* +* Is x is out of long range or NaN? * +*******************************************************************************/ + { + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + if ( target ) // pin result + return ( LONG_MAX ); + else + return ( LONG_MIN ); + } + + if ( target ) +/******************************************************************************* +* Is sign of x is "+"? * +*******************************************************************************/ + { + if ( x < 2147483647.5 ) +/******************************************************************************* +* x is in the range of a long. * +*******************************************************************************/ + { + y = ( x + doubleToLong ) - doubleToLong; // round at binary point + if ( y != x ) + { // inexact case + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kTZ.dbl )); // truncate rounding + z = x + 0.5; // truncate x + 0.5 + argument.dbl = z + doubleToLong; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( ( long ) argument.words.lo ); + } + + argument.dbl = y + doubleToLong; // force result into argument.words.lo + return ( ( long ) argument.words.lo ); // return long result + } +/******************************************************************************* +* Rounded positive x is out of the range of a long. * +*******************************************************************************/ + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( LONG_MAX ); // return pinned result + } +/******************************************************************************* +* x < 0.0 and may or may not be out of the range of a long. * +*******************************************************************************/ + if ( x > -2147483648.5 ) +/******************************************************************************* +* x is in the range of a long. * +*******************************************************************************/ + { + y = ( x + doubleToLong ) - doubleToLong; // round at binary point + if ( y != x ) + { // inexact case + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kUP.dbl )); // round up + z = x - 0.5; // truncate x - 0.5 + argument.dbl = z + doubleToLong; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( ( long ) argument.words.lo ); + } + + argument.dbl = y + doubleToLong; + return ( ( long ) argument.words.lo ); // return long result + } +/******************************************************************************* +* Rounded negative x is out of the range of a long. * +*******************************************************************************/ + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); + OldEnvironment.words.lo |= SET_INVALID; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + return ( LONG_MIN ); // return pinned result + } + +/******************************************************************************* +* * +* The function trunc truncates its double argument to integral value * +* and returns the result in double format. This function signals * +* 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; // xhi <- high half of |x| + target = ( argument.words.hi < signMask ); // flag positive sign + + if ( xhi < 0x43300000ul ) +/******************************************************************************* +* Is |x| < 2.0^53? * +*******************************************************************************/ + { + if ( xhi < 0x3ff00000ul ) +/******************************************************************************* +* Is |x| < 1.0? * +*******************************************************************************/ + { + if ( ( xhi | argument.words.lo ) != 0ul ) + { // raise deserved INEXACT + asm ("mffs %0" : "=f" (OldEnvironment.dbl)); + OldEnvironment.words.lo |= 0x02000000ul; + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); + } + if ( target ) // return properly signed zero + return ( 0.0 ); + else + return ( -0.0 ); + } +/******************************************************************************* +* Is 1.0 < |x| < 2.0^52? * +*******************************************************************************/ + if ( target ) + { + y = ( x + twoTo52 ) - twoTo52; // round at binary point + if ( y > x ) + return ( y - 1.0 ); + else + return ( y ); + } + + else + { + y = ( x - twoTo52 ) + twoTo52; // round at binary point. + if ( y < x ) + return ( y + 1.0 ); + else + return ( y ); + } + } +/******************************************************************************* +* Is |x| >= 2.0^52 or x is a NaN. * +*******************************************************************************/ + return ( x ); + } + +/******************************************************************************* +* The modf family of functions separate a floating-point number into its * +* fractional and integral parts, returning the fractional part and writing * +* the integral part in floating-point format to the object pointed to by a * +* pointer argument. If the input argument is integral or infinite in * +* value, the return value is a zero with the sign of the input argument. * +* The modf family of functions raises no floating-point exceptions. older * +* implemenation set the INVALID flag due to signaling NaN input. * +* * +*******************************************************************************/ + +/******************************************************************************* +* modf is the double implementation. * +*******************************************************************************/ + +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; // |x| high bit pattern + signBit = ( argument.words.hi & 0x80000000ul ); // isolate sign bit + if (xHead == 0x7ff81fe0) + signBit = signBit | 0; + + if ( xHead < 0x43300000ul ) +/******************************************************************************* +* Is |x| < 2.0^53? * +*******************************************************************************/ + { + if ( xHead < 0x3ff00000ul ) +/******************************************************************************* +* Is |x| < 1.0? * +*******************************************************************************/ + { + argument.words.hi = signBit; // truncate to zero + argument.words.lo = 0ul; + *iptr = argument.dbl; + return ( x ); + } +/******************************************************************************* +* Is 1.0 < |x| < 2.0^52? * +*******************************************************************************/ + asm ("mffs %0" : "=f" (OldEnvironment)); // save environment + // round toward zero + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( TOWARDZERO.dbl )); + if ( signBit == 0ul ) // truncate to integer + xtrunc = ( x + twoTo52 ) - twoTo52; + else + xtrunc = ( x - twoTo52 ) + twoTo52; + // restore caller's env + asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment )); + *iptr = xtrunc; // store integral part + if ( x != xtrunc ) // nonzero fraction + return ( x - xtrunc ); + else + { // zero with x's sign + argument.words.hi = signBit; + argument.words.lo = 0ul; + return ( argument.dbl ); + } + } + + *iptr = x; // x is integral or NaN + if ( x != x ) // NaN is returned + return x; + else + { // zero with x's sign + argument.words.hi = signBit; + argument.words.lo = 0ul; + return ( argument.dbl ); + } + } diff --git a/libm/powerpc/scalb.c b/libm/powerpc/scalb.c new file mode 100644 index 000000000..98a2b7d3f --- /dev/null +++ b/libm/powerpc/scalb.c @@ -0,0 +1,85 @@ +/*********************************************************************** +** File: scalb.c +** +** Contains: C source code for implementations of floating-point +** scalb functions defined in header . In +** particular, this file contains implementations of +** functions scalb and scalbl for double and long double +** formats on PowerPC platforms. +** +** Written by: Jon Okada, SANEitation Engineer, ext. 4-4838 +** +** Copyright: © 1992 by Apple Computer, Inc., all rights reserved +** +** Change History ( most recent first ): +** +** 28 May 97 ali made an speed improvement for large n, +** removed scalbl. +** 12 Dec 92 JPO First created. +** +***********************************************************************/ + +typedef union + { + struct { +#if defined(__BIG_ENDIAN__) + unsigned long int hi; + unsigned long int lo; +#else + unsigned long int lo; + unsigned long int hi; +#endif + } words; + double dbl; + } DblInHex; + +static const double twoTo1023 = 8.988465674311579539e307; // 0x1p1023 +static const double twoToM1022 = 2.225073858507201383e-308; // 0x1p-1022 + + +/*********************************************************************** + double scalb( double x, long int n ) returns its argument x scaled + by the factor 2^m. NaNs, signed zeros, and infinities are propagated + by this function regardless of the value of n. + + Exceptions: OVERFLOW/INEXACT or UNDERFLOW inexact may occur; + INVALID for signaling NaN inputs ( quiet NaN returned ). + + Calls: none. +***********************************************************************/ + +double scalb ( double x, int n ) + { + DblInHex xInHex; + + xInHex.words.lo = 0UL; // init. low half of xInHex + + if ( n > 1023 ) + { // large positive scaling + if ( n > 2097 ) // huge scaling + return ( ( x * twoTo1023 ) * twoTo1023 ) * twoTo1023; + while ( n > 1023 ) + { // scale reduction loop + x *= twoTo1023; // scale x by 2^1023 + n -= 1023; // reduce n by 1023 + } + } + + else if ( n < -1022 ) + { // large negative scaling + if ( n < -2098 ) // huge negative scaling + return ( ( x * twoToM1022 ) * twoToM1022 ) * twoToM1022; + while ( n < -1022 ) + { // scale reduction loop + x *= twoToM1022; // scale x by 2^( -1022 ) + n += 1022; // incr n by 1022 + } + } + +/******************************************************************************* +* -1022 <= n <= 1023; convert n to double scale factor. * +*******************************************************************************/ + + xInHex.words.hi = ( ( unsigned long ) ( n + 1023 ) ) << 20; + return ( x * xInHex.dbl ); + } diff --git a/libm/powerpc/sign.c b/libm/powerpc/sign.c new file mode 100644 index 000000000..0bf2f3829 --- /dev/null +++ b/libm/powerpc/sign.c @@ -0,0 +1,56 @@ +/******************************************************************************* +* * +* File sign.c, * +* Functions copysign and __signbitd. * +* For PowerPC based machines. * +* * +* Copyright © 1991, 2001 Apple Computer, Inc. All rights reserved. * +* * +* Written by Ali Sazegari, started on June 1991. * +* * +* August 26 1991: no CFront Version 1.1d17 warnings. * +* September 06 1991: passes the test suite with invalid raised on * +* signaling nans. sane rom code behaves the same. * +* September 24 1992: took the ̉#include support.hÓ out. * +* Dcember 02 1992: PowerPC port. * +* July 20 1994: __fabs added * +* July 21 1994: deleted unnecessary functions: neg, COPYSIGNnew, * +* and SIGNNUMnew. * +* April 11 2001: first port to os x using gcc. * +* removed fabs and deffered to gcc for direct * +* instruction generation. * +* * +*******************************************************************************/ + +#include "fp_private.h" + +/******************************************************************************* +* * +* Function copysign. * +* Implementation of copysign for the PowerPC. * +* * +******************************************************************************** +* Note: The order of the operands in this function is reversed from that * +* suggested in the IEEE standard 754. * +*******************************************************************************/ + +double copysign ( double arg2, double arg1 ) + { + union + { + dHexParts hex; + double dbl; + } x, y; + +/******************************************************************************* +* No need to flush NaNs out. * +*******************************************************************************/ + + x.dbl = arg1; + y.dbl = arg2; + + y.hex.high = y.hex.high & 0x7FFFFFFF; + y.hex.high = ( y.hex.high | ( x.hex.high & dSgnMask ) ); + + return y.dbl; + } diff --git a/libm/rndint.c b/libm/rndint.c deleted file mode 100644 index 7f8c183d4..000000000 --- a/libm/rndint.c +++ /dev/null @@ -1,632 +0,0 @@ -/******************************************************************************* -** File: rndint.c -** -** Contains: C source code for implementations of floating-point -** functions which round to integral value or format, as -** defined in header . 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 -** 03 Mar 01 ali first port to os x using gcc, added the crucial __setflm -** definition. -** 1. removed double_t, put in double for now. -** 2. removed iclass from nearbyint. -** 3. removed wrong comments intrunc. -** 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, -** rint is more elegant, but slower by %30 than the taligent one. -** 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c -** 15 Sep 94 ali Major overhaul and performance improvements of all functions. -** 20 Jul 94 PAF New faster version -** 16 Jul 93 ali Added the modfl function. -** 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 -** separate file. -** 15 Dec 92 JPO Added __itrunc implementation and modified -** rinttol to include conversion from double -** to long int format. Modified roundtol to -** call __itrunc. -** 10 Dec 92 JPO Added modf (double) implementation. -** 04 Dec 92 JPO First created. -** -*******************************************************************************/ - -#include -#include - -#if !defined(__ppc__) -#define asm(x) -#endif - -#define SET_INVALID 0x01000000UL - -typedef union - { - struct { -#if defined(__BIG_ENDIAN__) - unsigned long int hi; - unsigned long int lo; -#else - unsigned long int lo; - unsigned long int hi; -#endif - } words; - double dbl; - } DblInHex; - -static const unsigned long int signMask = 0x80000000ul; -static const double twoTo52 = 4503599627370496.0; -static const double doubleToLong = 4503603922337792.0; // 2^52 -static const DblInHex Huge = {{ 0x7FF00000, 0x00000000 }}; -static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }}; - -/******************************************************************************* -* * -* The function rint rounds its double argument to integral value * -* according to the current rounding direction and returns the result in * -* double format. This function signals inexact if an ordered return * -* value is not equal to the operand. * -* * -******************************************************************************** -* * -* This function calls: fabs. * -* * -*******************************************************************************/ - -/******************************************************************************* -* First, an elegant implementation. * -******************************************************************************** -* -*double rint ( double x ) -* { -* double y; -* -* y = twoTo52.fval; -* -* if ( fabs ( x ) >= y ) // huge case is exact -* return x; -* if ( x < 0 ) y = -y; // negative case -* y = ( x + y ) - y; // force rounding -* if ( y == 0.0 ) // zero results mirror sign of x -* y = copysign ( y, x ); -* return ( y ); -* } -******************************************************************************** -* Now a bit twidling version that is about %30 faster. * -*******************************************************************************/ - -#if defined(__ppc__) -double rint ( double x ) - { - DblInHex argument; - register double y; - unsigned long int xHead; - register long int target; - - argument.dbl = x; - xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x| - target = ( argument.words.hi < signMask ); // flags positive sign - - if ( xHead < 0x43300000ul ) -/******************************************************************************* -* Is |x| < 2.0^52? * -*******************************************************************************/ - { - if ( xHead < 0x3ff00000ul ) -/******************************************************************************* -* Is |x| < 1.0? * -*******************************************************************************/ - { - if ( target ) - y = ( x + twoTo52 ) - twoTo52; // round at binary point - else - y = ( x - twoTo52 ) + twoTo52; // round at binary point - if ( y == 0.0 ) - { // fix sign of zero result - if ( target ) - return ( 0.0 ); - else - return ( -0.0 ); - } - return y; - } - -/******************************************************************************* -* Is 1.0 < |x| < 2.0^52? * -*******************************************************************************/ - - if ( target ) - return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt. - else - return ( ( x - twoTo52 ) + twoTo52 ); - } - -/******************************************************************************* -* |x| >= 2.0^52 or x is a NaN. * -*******************************************************************************/ - return ( x ); - } -#endif /* __ppc__ */ - -/******************************************************************************* -* * -* The function nearbyint rounds its double argument to integral value * -* according to the current rounding direction and returns the result in * -* double format. This function does not signal inexact. * -* * -******************************************************************************** -* * -* This function calls fabs and copysign. * -* * -*******************************************************************************/ - -double nearbyint ( double x ) - { - double y; -#if defined(__ppc__) - double OldEnvironment; -#endif /* __ppc__ */ - - y = twoTo52; - - asm ("mffs %0" : "=f" (OldEnvironment)); /* get the environement */ - - if ( fabs ( x ) >= y ) /* huge case is exact */ - return x; - if ( x < 0 ) y = -y; /* negative case */ - y = ( x + y ) - y; /* force rounding */ - if ( y == 0.0 ) /* zero results mirror sign of x */ - y = copysign ( y, x ); -// restore old flags - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment )); - return ( y ); - } - -/******************************************************************************* -* * -* The function rinttol converts its double argument to integral value * -* according to the current rounding direction and returns the result in * -* long int format. This conversion signals invalid if the argument is a * -* NaN or the rounded intermediate result is out of range of the * -* destination long int format, and it delivers an unspecified result in * -* this case. This function signals inexact if the rounded result is * -* within range of the long int format but unequal to the operand. * -* * -*******************************************************************************/ - -long int rinttol ( double x ) - { - register double y; - DblInHex argument, OldEnvironment; - unsigned long int xHead; - register long int target; - - argument.dbl = x; - target = ( argument.words.hi < signMask ); // flag positive sign - xHead = argument.words.hi & 0x7ffffffful; // high 32 bits of x - - if ( target ) -/******************************************************************************* -* Sign of x is positive. * -*******************************************************************************/ - { - if ( xHead < 0x41dffffful ) - { // x is safely in long range - y = ( x + twoTo52 ) - twoTo52; // round at binary point - argument.dbl = y + doubleToLong; // force result into argument.words.lo - return ( ( long ) argument.words.lo ); - } - - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment - - if ( xHead > 0x41dffffful ) - { // x is safely out of long range - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( LONG_MAX ); - } - -/******************************************************************************* -* x > 0.0 and may or may not be out of range of long. * -*******************************************************************************/ - - y = ( x + twoTo52 ) - twoTo52; // do rounding - if ( y > ( double ) LONG_MAX ) - { // out of range of long - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( LONG_MAX ); - } - argument.dbl = y + doubleToLong; // in range - return ( ( long ) argument.words.lo ); // return result & flags - } - -/******************************************************************************* -* Sign of x is negative. * -*******************************************************************************/ - if ( xHead < 0x41e00000ul ) - { // x is safely in long range - y = ( x - twoTo52 ) + twoTo52; - argument.dbl = y + doubleToLong; - return ( ( long ) argument.words.lo ); - } - - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment - - if ( xHead > 0x41e00000ul ) - { // x is safely out of long range - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( LONG_MIN ); - } - -/******************************************************************************* -* x < 0.0 and may or may not be out of range of long. * -*******************************************************************************/ - - y = ( x - twoTo52 ) + twoTo52; // do rounding - if ( y < ( double ) LONG_MIN ) - { // out of range of long - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( LONG_MIN ); - } - argument.dbl = y + doubleToLong; // in range - return ( ( long ) argument.words.lo ); // return result & flags - } - -/******************************************************************************* -* * -* The function round rounds its double argument to integral value * -* according to the "add half to the magnitude and truncate" rounding of * -* Pascal's Round function and FORTRAN's ANINT function and returns the * -* result in double format. This function signals inexact if an ordered * -* 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; // xHead <- high half of |x| - target = ( argument.words.hi < signMask ); // flag positive sign - - if ( xHead < 0x43300000ul ) -/******************************************************************************* -* Is |x| < 2.0^52? * -*******************************************************************************/ - { - if ( xHead < 0x3ff00000ul ) -/******************************************************************************* -* Is |x| < 1.0? * -*******************************************************************************/ - { - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment - if ( xHead < 0x3fe00000ul ) -/******************************************************************************* -* Is |x| < 0.5? * -*******************************************************************************/ - { - if ( ( xHead | argument.words.lo ) != 0ul ) - OldEnvironment.words.lo |= 0x02000000ul; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - if ( target ) - return ( 0.0 ); - else - return ( -0.0 ); - } -/******************************************************************************* -* Is 0.5 ² |x| < 1.0? * -*******************************************************************************/ - OldEnvironment.words.lo |= 0x02000000ul; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - if ( target ) - return ( 1.0 ); - else - return ( -1.0 ); - } -/******************************************************************************* -* Is 1.0 < |x| < 2.0^52? * -*******************************************************************************/ - if ( target ) - { // positive x - y = ( x + twoTo52 ) - twoTo52; // round at binary point - if ( y == x ) // exact case - return ( x ); - z = x + 0.5; // inexact case - y = ( z + twoTo52 ) - twoTo52; // round at binary point - if ( y > z ) - return ( y - 1.0 ); - else - return ( y ); - } - -/******************************************************************************* -* Is x < 0? * -*******************************************************************************/ - else - { - y = ( x - twoTo52 ) + twoTo52; // round at binary point - if ( y == x ) - return ( x ); - z = x - 0.5; - y = ( z - twoTo52 ) + twoTo52; // round at binary point - if ( y < z ) - return ( y + 1.0 ); - else - return ( y ); - } - } -/******************************************************************************* -* |x| >= 2.0^52 or x is a NaN. * -*******************************************************************************/ - return ( x ); - } - -/******************************************************************************* -* * -* The function roundtol converts its double argument to integral format * -* according to the "add half to the magnitude and chop" rounding mode of * -* Pascal's Round function and FORTRAN's NINT function. This conversion * -* signals invalid if the argument is a NaN or the rounded intermediate * -* result is out of range of the destination long int format, and it * -* delivers an unspecified result in this case. This function signals * -* inexact if the rounded result is within range of the long int format but * -* unequal to the operand. * -* * -*******************************************************************************/ - -long int roundtol ( double x ) - { - register double y, z; - DblInHex argument, OldEnvironment; - register unsigned long int xhi; - register long int target; -#if defined(__ppc__) - const DblInHex kTZ = {{ 0x0, 0x1 }}; - const DblInHex kUP = {{ 0x0, 0x2 }}; -#endif /* __ppc__ */ - - argument.dbl = x; - xhi = argument.words.hi & 0x7ffffffful; // high 32 bits of x - target = ( argument.words.hi < signMask ); // flag positive sign - - if ( xhi > 0x41e00000ul ) -/******************************************************************************* -* Is x is out of long range or NaN? * -*******************************************************************************/ - { - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - if ( target ) // pin result - return ( LONG_MAX ); - else - return ( LONG_MIN ); - } - - if ( target ) -/******************************************************************************* -* Is sign of x is "+"? * -*******************************************************************************/ - { - if ( x < 2147483647.5 ) -/******************************************************************************* -* x is in the range of a long. * -*******************************************************************************/ - { - y = ( x + doubleToLong ) - doubleToLong; // round at binary point - if ( y != x ) - { // inexact case - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kTZ.dbl )); // truncate rounding - z = x + 0.5; // truncate x + 0.5 - argument.dbl = z + doubleToLong; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( ( long ) argument.words.lo ); - } - - argument.dbl = y + doubleToLong; // force result into argument.words.lo - return ( ( long ) argument.words.lo ); // return long result - } -/******************************************************************************* -* Rounded positive x is out of the range of a long. * -*******************************************************************************/ - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( LONG_MAX ); // return pinned result - } -/******************************************************************************* -* x < 0.0 and may or may not be out of the range of a long. * -*******************************************************************************/ - if ( x > -2147483648.5 ) -/******************************************************************************* -* x is in the range of a long. * -*******************************************************************************/ - { - y = ( x + doubleToLong ) - doubleToLong; // round at binary point - if ( y != x ) - { // inexact case - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kUP.dbl )); // round up - z = x - 0.5; // truncate x - 0.5 - argument.dbl = z + doubleToLong; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( ( long ) argument.words.lo ); - } - - argument.dbl = y + doubleToLong; - return ( ( long ) argument.words.lo ); // return long result - } -/******************************************************************************* -* Rounded negative x is out of the range of a long. * -*******************************************************************************/ - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); - OldEnvironment.words.lo |= SET_INVALID; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - return ( LONG_MIN ); // return pinned result - } - -/******************************************************************************* -* * -* The function trunc truncates its double argument to integral value * -* and returns the result in double format. This function signals * -* 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; // xhi <- high half of |x| - target = ( argument.words.hi < signMask ); // flag positive sign - - if ( xhi < 0x43300000ul ) -/******************************************************************************* -* Is |x| < 2.0^53? * -*******************************************************************************/ - { - if ( xhi < 0x3ff00000ul ) -/******************************************************************************* -* Is |x| < 1.0? * -*******************************************************************************/ - { - if ( ( xhi | argument.words.lo ) != 0ul ) - { // raise deserved INEXACT - asm ("mffs %0" : "=f" (OldEnvironment.dbl)); - OldEnvironment.words.lo |= 0x02000000ul; - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl )); - } - if ( target ) // return properly signed zero - return ( 0.0 ); - else - return ( -0.0 ); - } -/******************************************************************************* -* Is 1.0 < |x| < 2.0^52? * -*******************************************************************************/ - if ( target ) - { - y = ( x + twoTo52 ) - twoTo52; // round at binary point - if ( y > x ) - return ( y - 1.0 ); - else - return ( y ); - } - - else - { - y = ( x - twoTo52 ) + twoTo52; // round at binary point. - if ( y < x ) - return ( y + 1.0 ); - else - return ( y ); - } - } -/******************************************************************************* -* Is |x| >= 2.0^52 or x is a NaN. * -*******************************************************************************/ - return ( x ); - } - -/******************************************************************************* -* The modf family of functions separate a floating-point number into its * -* fractional and integral parts, returning the fractional part and writing * -* the integral part in floating-point format to the object pointed to by a * -* pointer argument. If the input argument is integral or infinite in * -* value, the return value is a zero with the sign of the input argument. * -* The modf family of functions raises no floating-point exceptions. older * -* implemenation set the INVALID flag due to signaling NaN input. * -* * -*******************************************************************************/ - -/******************************************************************************* -* modf is the double implementation. * -*******************************************************************************/ - -#if defined(__ppc__) -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; // |x| high bit pattern - signBit = ( argument.words.hi & 0x80000000ul ); // isolate sign bit - if (xHead == 0x7ff81fe0) - signBit = signBit | 0; - - if ( xHead < 0x43300000ul ) -/******************************************************************************* -* Is |x| < 2.0^53? * -*******************************************************************************/ - { - if ( xHead < 0x3ff00000ul ) -/******************************************************************************* -* Is |x| < 1.0? * -*******************************************************************************/ - { - argument.words.hi = signBit; // truncate to zero - argument.words.lo = 0ul; - *iptr = argument.dbl; - return ( x ); - } -/******************************************************************************* -* Is 1.0 < |x| < 2.0^52? * -*******************************************************************************/ - asm ("mffs %0" : "=f" (OldEnvironment)); // save environment - // round toward zero - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( TOWARDZERO.dbl )); - if ( signBit == 0ul ) // truncate to integer - xtrunc = ( x + twoTo52 ) - twoTo52; - else - xtrunc = ( x - twoTo52 ) + twoTo52; - // restore caller's env - asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment )); - *iptr = xtrunc; // store integral part - if ( x != xtrunc ) // nonzero fraction - return ( x - xtrunc ); - else - { // zero with x's sign - argument.words.hi = signBit; - argument.words.lo = 0ul; - return ( argument.dbl ); - } - } - - *iptr = x; // x is integral or NaN - if ( x != x ) // NaN is returned - return x; - else - { // zero with x's sign - argument.words.hi = signBit; - argument.words.lo = 0ul; - return ( argument.dbl ); - } - } -#endif /* __ppc__ */ diff --git a/libm/s_ceil.c b/libm/s_ceil.c index f17b31447..8616d0f54 100644 --- a/libm/s_ceil.c +++ b/libm/s_ceil.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_ceil.c 5.1 93/09/24 */ /* * ==================================================== @@ -79,4 +78,4 @@ static double huge = 1.0e300; INSERT_WORDS(x,i0,i1); return x; } -#endif /* !__ppc__ */ + diff --git a/libm/s_copysign.c b/libm/s_copysign.c index 666c34a6f..63261fc96 100644 --- a/libm/s_copysign.c +++ b/libm/s_copysign.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_copysign.c 5.1 93/09/24 */ /* * ==================================================== @@ -37,4 +36,4 @@ static char rcsid[] = "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $ SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000)); return x; } -#endif + diff --git a/libm/s_floor.c b/libm/s_floor.c index 375dc5a10..5a36b2d6f 100644 --- a/libm/s_floor.c +++ b/libm/s_floor.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_floor.c 5.1 93/09/24 */ /* * ==================================================== @@ -80,4 +79,3 @@ static double huge = 1.0e300; INSERT_WORDS(x,i0,i1); return x; } -#endif /* !__ppc__ */ diff --git a/libm/s_frexp.c b/libm/s_frexp.c index f187d8472..bfc9dba03 100644 --- a/libm/s_frexp.c +++ b/libm/s_frexp.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_frexp.c 5.1 93/09/24 */ /* * ==================================================== @@ -58,4 +57,3 @@ two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ SET_HIGH_WORD(x,hx); return x; } -#endif /* !__ppc__ */ diff --git a/libm/s_ldexp.c b/libm/s_ldexp.c index 5e7313e6e..085823aea 100644 --- a/libm/s_ldexp.c +++ b/libm/s_ldexp.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_ldexp.c 5.1 93/09/24 */ /* * ==================================================== @@ -31,4 +30,3 @@ static char rcsid[] = "$NetBSD: s_ldexp.c,v 1.6 1995/05/10 20:47:40 jtc Exp $"; if(!finite(value)||value==0.0) errno = ERANGE; return value; } -#endif /* !__ppc__ */ diff --git a/libm/s_logb.c b/libm/s_logb.c index 7ec1c3696..02bb99f3c 100644 --- a/libm/s_logb.c +++ b/libm/s_logb.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_logb.c 5.1 93/09/24 */ /* * ==================================================== @@ -41,4 +40,3 @@ static char rcsid[] = "$NetBSD: s_logb.c,v 1.8 1995/05/10 20:47:50 jtc Exp $"; else return (double) (ix-1023); } -#endif /* !__ppc__ */ diff --git a/libm/s_modf.c b/libm/s_modf.c index 2d3e5379b..9d71c01d1 100644 --- a/libm/s_modf.c +++ b/libm/s_modf.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_modf.c 5.1 93/09/24 */ /* * ==================================================== @@ -82,4 +81,3 @@ static double one = 1.0; } } } -#endif /* !__ppc__ */ diff --git a/libm/s_rint.c b/libm/s_rint.c index b2d9c0e79..880885759 100644 --- a/libm/s_rint.c +++ b/libm/s_rint.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)s_rint.c 5.1 93/09/24 */ /* * ==================================================== @@ -85,4 +84,3 @@ TWO52[2]={ w = TWO52[sx]+x; return w-TWO52[sx]; } -#endif /* !__ppc__ */ diff --git a/libm/scalb.c b/libm/scalb.c deleted file mode 100644 index 03d2de9dc..000000000 --- a/libm/scalb.c +++ /dev/null @@ -1,87 +0,0 @@ -#if defined(__ppc__) -/*********************************************************************** -** File: scalb.c -** -** Contains: C source code for implementations of floating-point -** scalb functions defined in header . In -** particular, this file contains implementations of -** functions scalb and scalbl for double and long double -** formats on PowerPC platforms. -** -** Written by: Jon Okada, SANEitation Engineer, ext. 4-4838 -** -** Copyright: © 1992 by Apple Computer, Inc., all rights reserved -** -** Change History ( most recent first ): -** -** 28 May 97 ali made an speed improvement for large n, -** removed scalbl. -** 12 Dec 92 JPO First created. -** -***********************************************************************/ - -typedef union - { - struct { -#if defined(__BIG_ENDIAN__) - unsigned long int hi; - unsigned long int lo; -#else - unsigned long int lo; - unsigned long int hi; -#endif - } words; - double dbl; - } DblInHex; - -static const double twoTo1023 = 8.988465674311579539e307; // 0x1p1023 -static const double twoToM1022 = 2.225073858507201383e-308; // 0x1p-1022 - - -/*********************************************************************** - double scalb( double x, long int n ) returns its argument x scaled - by the factor 2^m. NaNs, signed zeros, and infinities are propagated - by this function regardless of the value of n. - - Exceptions: OVERFLOW/INEXACT or UNDERFLOW inexact may occur; - INVALID for signaling NaN inputs ( quiet NaN returned ). - - Calls: none. -***********************************************************************/ - -double scalb ( double x, int n ) - { - DblInHex xInHex; - - xInHex.words.lo = 0UL; // init. low half of xInHex - - if ( n > 1023 ) - { // large positive scaling - if ( n > 2097 ) // huge scaling - return ( ( x * twoTo1023 ) * twoTo1023 ) * twoTo1023; - while ( n > 1023 ) - { // scale reduction loop - x *= twoTo1023; // scale x by 2^1023 - n -= 1023; // reduce n by 1023 - } - } - - else if ( n < -1022 ) - { // large negative scaling - if ( n < -2098 ) // huge negative scaling - return ( ( x * twoToM1022 ) * twoToM1022 ) * twoToM1022; - while ( n < -1022 ) - { // scale reduction loop - x *= twoToM1022; // scale x by 2^( -1022 ) - n += 1022; // incr n by 1022 - } - } - -/******************************************************************************* -* -1022 <= n <= 1023; convert n to double scale factor. * -*******************************************************************************/ - - xInHex.words.hi = ( ( unsigned long ) ( n + 1023 ) ) << 20; - return ( x * xInHex.dbl ); - } -#endif /* __ppc__ */ diff --git a/libm/sign.c b/libm/sign.c deleted file mode 100644 index 524d6afe3..000000000 --- a/libm/sign.c +++ /dev/null @@ -1,58 +0,0 @@ -#if defined(__ppc__) -/******************************************************************************* -* * -* File sign.c, * -* Functions copysign and __signbitd. * -* For PowerPC based machines. * -* * -* Copyright © 1991, 2001 Apple Computer, Inc. All rights reserved. * -* * -* Written by Ali Sazegari, started on June 1991. * -* * -* August 26 1991: no CFront Version 1.1d17 warnings. * -* September 06 1991: passes the test suite with invalid raised on * -* signaling nans. sane rom code behaves the same. * -* September 24 1992: took the ̉#include support.hÓ out. * -* Dcember 02 1992: PowerPC port. * -* July 20 1994: __fabs added * -* July 21 1994: deleted unnecessary functions: neg, COPYSIGNnew, * -* and SIGNNUMnew. * -* April 11 2001: first port to os x using gcc. * -* removed fabs and deffered to gcc for direct * -* instruction generation. * -* * -*******************************************************************************/ - -#include "fp_private.h" - -/******************************************************************************* -* * -* Function copysign. * -* Implementation of copysign for the PowerPC. * -* * -******************************************************************************** -* Note: The order of the operands in this function is reversed from that * -* suggested in the IEEE standard 754. * -*******************************************************************************/ - -double copysign ( double arg2, double arg1 ) - { - union - { - dHexParts hex; - double dbl; - } x, y; - -/******************************************************************************* -* No need to flush NaNs out. * -*******************************************************************************/ - - x.dbl = arg1; - y.dbl = arg2; - - y.hex.high = y.hex.high & 0x7FFFFFFF; - y.hex.high = ( y.hex.high | ( x.hex.high & dSgnMask ) ); - - return y.dbl; - } -#endif /* __ppc__ */ diff --git a/libm/w_scalb.c b/libm/w_scalb.c index bde5f705a..50026bed9 100644 --- a/libm/w_scalb.c +++ b/libm/w_scalb.c @@ -1,4 +1,3 @@ -#if !defined(__ppc__) /* @(#)w_scalb.c 5.1 93/09/24 */ /* * ==================================================== @@ -59,4 +58,3 @@ static char rcsid[] = "$NetBSD: w_scalb.c,v 1.6 1995/05/10 20:49:48 jtc Exp $"; return z; #endif } -#endif /* !__ppc__ */ -- cgit v1.2.3