|
|
|
/* GSL - Generic Sound Layer
|
|
|
|
* Copyright (C) 1999, 2001 Tim Janik
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General
|
|
|
|
* Public License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
#ifndef __GSL_IEEE754_H__
|
|
|
|
#define __GSL_IEEE754_H__
|
|
|
|
|
|
|
|
#include <gsl/gsldefs.h>
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
|
|
|
|
|
|
/* IEEE 754 single precision floating point layout:
|
|
|
|
* 31 30 23 22 0
|
|
|
|
* +--------+---------------+---------------+
|
|
|
|
* | s 1bit | e[30:23] 8bit | f[22:0] 23bit |
|
|
|
|
* +--------+---------------+---------------+
|
|
|
|
* B0------------------->B1------->B2-->B3-->
|
|
|
|
*
|
|
|
|
* IEEE 754 double precision floating point layout:
|
|
|
|
* 63 62 52 51 32 31 0
|
|
|
|
* +--------+----------------+----------------+ +---------------+
|
|
|
|
* | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit |
|
|
|
|
* +--------+----------------+----------------+ +---------------+
|
|
|
|
* B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7->
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* floating point type related constants */
|
|
|
|
#define GSL_FLOAT_BIAS (127)
|
|
|
|
#define GSL_FLOAT_MAX_NORMAL (3.40282347e+38) /* 7f7fffff */
|
|
|
|
#define GSL_FLOAT_MIN_NORMAL (1.17549435e-38) /* 00800000 */
|
|
|
|
#define GSL_FLOAT_MAX_SUBNORMAL (1.17549421e-38) /* 007fffff */
|
|
|
|
#define GSL_FLOAT_MIN_SUBNORMAL (1.40129846e-45) /* 00000001 */
|
|
|
|
#define GSL_DOUBLE_BIAS (1023)
|
|
|
|
#define GSL_DOUBLE_MAX_NORMAL (1.7976931348623157e+308) /* 7fefffff ffffffff */
|
|
|
|
#define GSL_DOUBLE_MIN_NORMAL (2.2250738585072014e-308) /* 00100000 00000000 */
|
|
|
|
#define GSL_DOUBLE_MAX_SUBNORMAL (2.2250738585072009e-308) /* 000fffff ffffffff */
|
|
|
|
#define GSL_DOUBLE_MIN_SUBNORMAL (4.9406564584124654e-324) /* 00000000 00000001 */
|
|
|
|
#define GSL_DOUBLE_INF (_gsl_dinf_union.d)
|
|
|
|
#define GSL_DOUBLE_NAN (_gsl_dnan_union.d)
|
|
|
|
#define GSL_FLOAT_INF (_gsl_finf_union.f)
|
|
|
|
#define GSL_FLOAT_NAN (_gsl_fnan_union.f)
|
|
|
|
|
|
|
|
/* multiply with base2 exponent to get base10 exponent (for nomal numbers) */
|
|
|
|
#define GSL_LOG_2_BASE_10 (0.30102999566398119521)
|
|
|
|
|
|
|
|
/* the following macros work only on variables
|
|
|
|
* and evaluate arguments multiple times
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* single precision value checks */
|
|
|
|
#define GSL_FLOAT_IS_ZERO(f) ((f) == 0.0) /* compiler knows this one */
|
|
|
|
#define GSL_FLOAT_IS_NORMAL(f) (GSL_FLOAT_PARTS (f).mpn.biased_exponent > 0 && \
|
|
|
|
GSL_FLOAT_PARTS (f).mpn.biased_exponent < 255)
|
|
|
|
#define GSL_FLOAT_IS_SUBNORMAL(f) (GSL_FLOAT_PARTS (f).mpn.biased_exponent == 0 && \
|
|
|
|
GSL_FLOAT_PARTS (f).mpn.mantissa != 0)
|
|
|
|
#define GSL_FLOAT_IS_NANINF(f) (GSL_FLOAT_PARTS (f).mpn.biased_exponent == 255)
|
|
|
|
#define GSL_FLOAT_IS_NAN(f) (GSL_FLOAT_IS_NANINF (f) && GSL_FLOAT_PARTS (f).mpn.mantissa != 0)
|
|
|
|
#define GSL_FLOAT_IS_INF(f) (GSL_FLOAT_IS_NANINF (f) && GSL_FLOAT_PARTS (f).mpn.mantissa == 0)
|
|
|
|
#define GSL_FLOAT_IS_INF_POSITIVE(f) (GSL_FLOAT_IS_INF (f) && GSL_FLOAT_PARTS (f).mpn.sign == 0)
|
|
|
|
#define GSL_FLOAT_IS_INF_NEGATIVE(f) (GSL_FLOAT_IS_INF (f) && GSL_FLOAT_PARTS (f).mpn.sign == 1)
|
|
|
|
#define GSL_FLOAT_SIGN(f) (GSL_FLOAT_PARTS (f).mpn.sign)
|
|
|
|
|
|
|
|
/* double precision value checks */
|
|
|
|
#define GSL_DOUBLE_IS_ZERO(d) ((d) == 0.0) /* compiler knows this one */
|
|
|
|
#define GSL_DOUBLE_IS_NORMAL(d) (GSL_DOUBLE_PARTS (d).mpn.biased_exponent > 0 && \
|
|
|
|
GSL_DOUBLE_PARTS (d).mpn.biased_exponent < 2047)
|
|
|
|
#define GSL_DOUBLE_IS_SUBNORMAL(d) (GSL_DOUBLE_PARTS (d).mpn.biased_exponent == 0 && \
|
|
|
|
(GSL_DOUBLE_PARTS (d).mpn.mantissa_low != 0 || \
|
|
|
|
GSL_DOUBLE_PARTS (d).mpn.mantissa_high != 0))
|
|
|
|
#define GSL_DOUBLE_IS_NANINF(d) (GSL_DOUBLE_PARTS (d).mpn.biased_exponent == 2047)
|
|
|
|
#define GSL_DOUBLE_IS_NAN(d) (GSL_DOUBLE_IS_NANINF (d) && \
|
|
|
|
(GSL_DOUBLE_PARTS (d).mpn.mantissa_low != 0 || \
|
|
|
|
GSL_DOUBLE_PARTS (d).mpn.mantissa_high != 0))
|
|
|
|
#define GSL_DOUBLE_IS_INF(d) (GSL_DOUBLE_IS_NANINF (d) && \
|
|
|
|
GSL_DOUBLE_PARTS (d).mpn.mantissa_low == 0 && \
|
|
|
|
GSL_DOUBLE_PARTS (d).mpn.mantissa_high == 0)
|
|
|
|
#define GSL_DOUBLE_IS_INF_POSITIVE(d) (GSL_DOUBLE_IS_INF (d) && GSL_DOUBLE_PARTS (d).mpn.sign == 0)
|
|
|
|
#define GSL_DOUBLE_IS_INF_NEGATIVE(d) (GSL_DOUBLE_IS_INF (d) && GSL_DOUBLE_PARTS (d).mpn.sign == 1)
|
|
|
|
#define GSL_DOUBLE_SIGN(d) (GSL_DOUBLE_PARTS (d).mpn.sign)
|
|
|
|
|
|
|
|
/* get structured parts of floating point numbers */
|
|
|
|
#define GSL_FLOAT_PARTS(f) (*((GslFloatIEEE754*) &(f)))
|
|
|
|
#define GSL_DOUBLE_PARTS(d) (*((GslDoubleIEEE754*) &(d)))
|
|
|
|
|
|
|
|
/* --- rounding --- */
|
|
|
|
typedef unsigned short int GslFpuState;
|
|
|
|
#if defined (__i386__) && defined (__GNUC__)
|
|
|
|
/* setting/restoring rounding mode shouldn't actually
|
|
|
|
* be necessary as round-to-nearest is the hardware
|
|
|
|
* default (can be checked with gsl_fpu_okround()).
|
|
|
|
*/
|
|
|
|
static inline void gsl_fpu_setround (GslFpuState *cw);
|
|
|
|
static inline int gsl_fpu_okround (void);
|
|
|
|
static inline void gsl_fpu_restore (GslFpuState cv);
|
|
|
|
static inline int gsl_ftoi /* nearest */ (float f) G_GNUC_CONST;
|
|
|
|
static inline int gsl_dtoi /* nearest */ (double f) G_GNUC_CONST;
|
|
|
|
/* fallbacks for the !386 case are below */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* --- implementation bits --- */
|
|
|
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
float v_float;
|
|
|
|
struct {
|
|
|
|
unsigned int mantissa : 23;
|
|
|
|
unsigned int biased_exponent : 8;
|
|
|
|
unsigned int sign : 1;
|
|
|
|
} mpn;
|
|
|
|
} GslFloatIEEE754;
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
double v_double;
|
|
|
|
struct {
|
|
|
|
unsigned int mantissa_low : 32;
|
|
|
|
unsigned int mantissa_high : 20;
|
|
|
|
unsigned int biased_exponent : 11;
|
|
|
|
unsigned int sign : 1;
|
|
|
|
} mpn;
|
|
|
|
} GslDoubleIEEE754;
|
|
|
|
#define _GSL_DOUBLE_INF_BYTES { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f }
|
|
|
|
#define _GSL_DOUBLE_NAN_BYTES { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f }
|
|
|
|
#define _GSL_FLOAT_INF_BYTES { 0x00, 0x00, 0x80, 0x7f }
|
|
|
|
#define _GSL_FLOAT_NAN_BYTES { 0x00, 0x00, 0xc0, 0x7f }
|
|
|
|
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
float v_float;
|
|
|
|
struct {
|
|
|
|
unsigned int sign : 1;
|
|
|
|
unsigned int biased_exponent : 8;
|
|
|
|
unsigned int mantissa : 23;
|
|
|
|
} mpn;
|
|
|
|
} GslFloatIEEE754;
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
double v_double;
|
|
|
|
struct {
|
|
|
|
unsigned int sign : 1;
|
|
|
|
unsigned int biased_exponent : 11;
|
|
|
|
unsigned int mantissa_high : 20;
|
|
|
|
unsigned int mantissa_low : 32;
|
|
|
|
} mpn;
|
|
|
|
} GslDoubleIEEE754;
|
|
|
|
#define _GSL_DOUBLE_INF_BYTES { 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
|
|
|
#define _GSL_DOUBLE_NAN_BYTES { 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
|
|
|
#define _GSL_FLOAT_INF_BYTES { 0x7f, 0x80, 0x00, 0x00 }
|
|
|
|
#define _GSL_FLOAT_NAN_BYTES { 0x7f, 0xc0, 0x00, 0x00 }
|
|
|
|
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
|
|
|
#error unknown ENDIAN type
|
|
|
|
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
|
|
|
|
|
|
|
static const union { unsigned char c[8]; double d; } _gsl_dnan_union = { _GSL_DOUBLE_NAN_BYTES };
|
|
|
|
static const union { unsigned char c[8]; double d; } _gsl_dinf_union = { _GSL_DOUBLE_INF_BYTES };
|
|
|
|
static const union { unsigned char c[4]; float f; } _gsl_fnan_union = { _GSL_FLOAT_NAN_BYTES };
|
|
|
|
static const union { unsigned char c[4]; float f; } _gsl_finf_union = { _GSL_FLOAT_INF_BYTES };
|
|
|
|
|
|
|
|
#if defined (__i386__) && defined (__GNUC__)
|
|
|
|
static inline void
|
|
|
|
gsl_fpu_setround (GslFpuState *cw)
|
|
|
|
{
|
|
|
|
GslFpuState cv;
|
|
|
|
|
|
|
|
__asm__ ("fnstcw %0"
|
|
|
|
: "=m" (*&cv));
|
|
|
|
*cw = cv;
|
|
|
|
cv &= ~0x0c00;
|
|
|
|
__asm__ ("fldcw %0"
|
|
|
|
:
|
|
|
|
: "m" (*&cv));
|
|
|
|
}
|
|
|
|
static inline int
|
|
|
|
gsl_fpu_okround (void)
|
|
|
|
{
|
|
|
|
GslFpuState cv;
|
|
|
|
|
|
|
|
__asm__ ("fnstcw %0"
|
|
|
|
: "=m" (*&cv));
|
|
|
|
return !(cv & 0x0c00);
|
|
|
|
}
|
|
|
|
static inline void
|
|
|
|
gsl_fpu_restore (GslFpuState cv)
|
|
|
|
{
|
|
|
|
__asm__ ("fldcw %0"
|
|
|
|
:
|
|
|
|
: "m" (*&cv));
|
|
|
|
}
|
|
|
|
static inline int G_GNUC_CONST
|
|
|
|
gsl_ftoi (float f)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
__asm__ ("fistl %0"
|
|
|
|
: "=m" (r)
|
|
|
|
: "t" (f));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
static inline int G_GNUC_CONST
|
|
|
|
gsl_dtoi (double f)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
__asm__ ("fistl %0"
|
|
|
|
: "=m" (r)
|
|
|
|
: "t" (f));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
#else /* !386 */
|
|
|
|
# define gsl_fpu_setround(p) ((void) (p));
|
|
|
|
# define gsl_fpu_okround() (1)
|
|
|
|
# define gsl_fpu_restore(x) /* nop */
|
|
|
|
static inline int G_GNUC_CONST
|
|
|
|
gsl_ftoi (float v)
|
|
|
|
{
|
|
|
|
return v < -0.0 ? v - 0.5 : v + 0.5;
|
|
|
|
}
|
|
|
|
static inline int G_GNUC_CONST
|
|
|
|
gsl_dtoi (double v)
|
|
|
|
{
|
|
|
|
return v < -0.0 ? v - 0.5 : v + 0.5;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
|
|
#endif /* __GSL_IEEE754_H__ */
|