summaryrefslogtreecommitdiff
path: root/libm/fpmacros.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-11-22 14:04:29 +0000
committerEric Andersen <andersen@codepoet.org>2001-11-22 14:04:29 +0000
commit7ce331c01ce6eb7b3f5c715a38a24359da9c6ee2 (patch)
tree3a7e8476e868ae15f4da1b7ce26b2db6f434468c /libm/fpmacros.c
parentc117dd5fb183afb1a4790a6f6110d88704be6bf8 (diff)
Totally rework the math library, this time based on the MacOs X
math library (which is itself based on the math lib from FreeBSD). -Erik
Diffstat (limited to 'libm/fpmacros.c')
-rw-r--r--libm/fpmacros.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/libm/fpmacros.c b/libm/fpmacros.c
new file mode 100644
index 000000000..6c5abbe87
--- /dev/null
+++ b/libm/fpmacros.c
@@ -0,0 +1,239 @@
+/***********************************************************************
+** File: fpmacros.c
+**
+** Contains: C source code for implementations of floating-point
+** functions which involve float format numbers, as
+** defined in header <fp.h>. In particular, this file
+** contains implementations of functions
+** __fpclassify(d,f), __isnormal(d,f), __isfinite(d,f),
+** __isnan(d,f), and __signbit(d,f). This file targets
+** PowerPC platforms.
+**
+** Written by: Robert A. Murley, Ali Sazegari
+**
+** Copyright: c 2001 by Apple Computer, Inc., all rights reserved
+**
+** Change History (most recent first):
+**
+** 07 Jul 01 ram First created from fpfloatfunc.c, fp.c,
+** classify.c and sign.c in MathLib v3 Mac OS9.
+**
+***********************************************************************/
+
+#include "fp_private.h"
+
+#define SIGN_MASK 0x80000000
+#define NSIGN_MASK 0x7fffffff
+#define FEXP_MASK 0x7f800000
+#define FFRAC_MASK 0x007fffff
+
+/***********************************************************************
+ long int __fpclassifyf(float x) returns the classification code of the
+ argument x, as defined in <fp.h>.
+
+ Exceptions: INVALID signaled if x is a signaling NaN; in this case,
+ the FP_QNAN code is returned.
+
+ Calls: none
+***********************************************************************/
+
+long int __fpclassifyf ( float x )
+{
+ unsigned long int iexp;
+
+ union {
+ unsigned long int lval;
+ float fval;
+ } z;
+
+ z.fval = x;
+ iexp = z.lval & FEXP_MASK; /* isolate float exponent */
+
+ if (iexp == FEXP_MASK) { /* NaN or INF case */
+ if ((z.lval & 0x007fffff) == 0)
+ return (long int) FP_INFINITE;
+ else if ((z.lval & 0x00400000) != 0)
+ return (long int) FP_QNAN;
+ else
+ return (long int) FP_SNAN;
+ }
+
+ if (iexp != 0) /* normal float */
+ return (long int) FP_NORMAL;
+
+ if (x == 0.0)
+ return (long int) FP_ZERO; /* zero */
+ else
+ return (long int) FP_SUBNORMAL; /* must be subnormal */
+}
+
+
+/***********************************************************************
+ Function __fpclassify,
+ Implementation of classify of a double number for the PowerPC.
+
+ Exceptions: INVALID signaled if x is a signaling NaN; in this case,
+ the FP_QNAN code is returned.
+
+ Calls: none
+***********************************************************************/
+
+long int __fpclassify ( double arg )
+{
+ register unsigned long int exponent;
+ union
+ {
+ dHexParts hex;
+ double dbl;
+ } x;
+
+ x.dbl = arg;
+
+ exponent = x.hex.high & dExpMask;
+ if ( exponent == dExpMask )
+ {
+ if ( ( ( x.hex.high & dHighMan ) | x.hex.low ) == 0 )
+ return (long int) FP_INFINITE;
+ else
+ return ( x.hex.high & 0x00080000 ) ? FP_QNAN : FP_SNAN;
+ }
+ else if ( exponent != 0)
+ return (long int) FP_NORMAL;
+ else {
+ if ( arg == 0.0 )
+ return (long int) FP_ZERO;
+ else
+ return (long int) FP_SUBNORMAL;
+ }
+}
+
+
+/***********************************************************************
+ long int __isnormalf(float x) returns nonzero if and only if x is a
+ normalized float number and zero otherwise.
+
+ Exceptions: INVALID is raised if x is a signaling NaN; in this case,
+ zero is returned.
+
+ Calls: none
+***********************************************************************/
+
+long int __isnormalf ( float x )
+{
+ unsigned long int iexp;
+ union {
+ unsigned long int lval;
+ float fval;
+ } z;
+
+ z.fval = x;
+ iexp = z.lval & FEXP_MASK; /* isolate float exponent */
+ return ((iexp != FEXP_MASK) && (iexp != 0));
+}
+
+
+long int __isnorma ( double x )
+{
+ return ( __fpclassify ( x ) == FP_NORMAL );
+}
+
+
+/***********************************************************************
+ long int __isfinitef(float x) returns nonzero if and only if x is a
+ finite (normal, subnormal, or zero) float number and zero otherwise.
+
+ Exceptions: INVALID is raised if x is a signaling NaN; in this case,
+ zero is returned.
+
+ Calls: none
+***********************************************************************/
+
+long int __isfinitef ( float x )
+{
+ union {
+ unsigned long int lval;
+ float fval;
+ } z;
+
+ z.fval = x;
+ return ((z.lval & FEXP_MASK) != FEXP_MASK);
+}
+
+long int __isfinite ( double x )
+{
+ return ( __fpclassify ( x ) >= FP_ZERO );
+}
+
+
+
+/***********************************************************************
+ long int __isnanf(float x) returns nonzero if and only if x is a
+ NaN and zero otherwise.
+
+ Exceptions: INVALID is raised if x is a signaling NaN; in this case,
+ nonzero is returned.
+
+ Calls: none
+***********************************************************************/
+
+long int __isnanf ( float x )
+{
+ union {
+ unsigned long int lval;
+ float fval;
+ } z;
+
+ z.fval = x;
+ return (((z.lval&FEXP_MASK) == FEXP_MASK) && ((z.lval&FFRAC_MASK) != 0));
+}
+
+long int __isnan ( double x )
+{
+ long int class = __fpclassify(x);
+ return ( ( class == FP_SNAN ) || ( class == FP_QNAN ) );
+}
+
+
+/***********************************************************************
+ long int __signbitf(float x) returns nonzero if and only if the sign
+ bit of x is set and zero otherwise.
+
+ Exceptions: INVALID is raised if x is a signaling NaN.
+
+ Calls: none
+***********************************************************************/
+
+long int __signbitf ( float x )
+{
+ union {
+ unsigned long int lval;
+ float fval;
+ } z;
+
+ z.fval = x;
+ return ((z.lval & SIGN_MASK) != 0);
+}
+
+
+/***********************************************************************
+ Function sign of a double.
+ Implementation of sign bit for the PowerPC.
+
+ Calls: none
+***********************************************************************/
+
+long int __signbit ( double arg )
+{
+ union
+ {
+ dHexParts hex;
+ double dbl;
+ } x;
+ long int sign;
+
+ x.dbl = arg;
+ sign = ( ( x.hex.high & dSgnMask ) == dSgnMask ) ? 1 : 0;
+ return sign;
+}
+
+