summaryrefslogtreecommitdiff
path: root/math
diff options
context:
space:
mode:
Diffstat (limited to 'math')
-rw-r--r--math/Makefile16
-rw-r--r--math/math.h13
-rw-r--r--math/math_private.h124
3 files changed, 149 insertions, 4 deletions
diff --git a/math/Makefile b/math/Makefile
index e1caa2908f..730b5610e0 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -30,7 +30,7 @@ distribute := math_private.h machine/asm.h machine/endian.h
# Build the -lm library.
extra-libs := libm
-libm-routines := e_acos e_acosf e_acosh e_acoshf e_asin e_asinf \
+libm-routines = e_acos e_acosf e_acosh e_acoshf e_asin e_asinf \
e_atan2 e_atan2f e_atanh e_atanhf e_cosh e_coshf \
e_exp e_expf e_fmod e_fmodf e_hypot e_hypotf e_j0 \
e_j0f e_j1 e_j1f e_jn e_jnf e_lgamma_r e_lgammaf_r \
@@ -55,12 +55,22 @@ libm-routines := e_acos e_acosf e_acosh e_acoshf e_asin e_asinf \
w_j0f w_j1 w_j1f w_jn w_jnf w_lgamma w_lgamma_r \
w_lgammaf w_lgammaf_r w_log w_log10 w_log10f w_logf \
w_pow w_powf w_remainder w_remainderf w_scalb \
- w_scalbf w_sinh w_sinhf w_sqrt w_sqrtf
+ w_scalbf w_sinh w_sinhf w_sqrt w_sqrtf \
+ $(long-m-routines)
+
+ifeq ($(long-double-fcts),yes)
+long-m-routines := s_ceill s_copysignl s_fabsl s_finitel s_floorl \
+ s_nextafterl s_rintl s_significandl
+endif
# These functions are in libc instead of libm because __printf_fp
# calls them, so any program using printf will need them linked in,
# and we don't want to have to link every program with -lm.
-routines := s_isinf s_isinff s_isnan s_isnanf isinfl isnanl
+routines = s_isinf s_isinff s_isnan s_isnanf $(long-c-routines)
+
+ifeq ($(long-double-fcts),yes)
+long-c-routines := s_isinfl s_isnanl
+endif
include ../Rules
diff --git a/math/math.h b/math/math.h
index 7bec1300c2..7a6134a6f0 100644
--- a/math/math.h
+++ b/math/math.h
@@ -61,6 +61,7 @@ __BEGIN_DECLS
#undef __MATH_PRECNAME
#ifdef __USE_MISC
+
/* Include the file of declarations again, this type using `float'
instead of `double' and appending f to each function name. */
@@ -69,7 +70,17 @@ __BEGIN_DECLS
#include <mathcalls.h>
#undef _Mdouble_
#undef __MATH_PRECNAME
-#endif
+
+/* Include the file of declarations again, this type using `long double'
+ instead of `double' and appending l to each function name. */
+
+#define _Mdouble_ long double
+#define __MATH_PRECNAME(name,r) name##l##r
+#include <mathcalls.h>
+#undef _Mdouble_
+#undef __MATH_PRECNAME
+
+#endif /* Use misc. */
#ifdef __USE_MISC
diff --git a/math/math_private.h b/math/math_private.h
index 95f65a293b..c4ac857607 100644
--- a/math/math_private.h
+++ b/math/math_private.h
@@ -147,6 +147,93 @@ do { \
(d) = sf_u.value; \
} while (0)
+/* A union which permits us to convert between a long double and
+ three 32 bit ints. */
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+typedef union
+{
+ long double value;
+ struct
+ {
+ unsigned int sign_exponent:16;
+ unsigned int empty:16;
+ u_int32_t msw;
+ u_int32_t lsw;
+ } parts;
+} ieee_long_double_shape_type;
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+typedef union
+{
+ long double value;
+ struct
+ {
+ u_int32_t lsw;
+ u_int32_t msw;
+ unsigned int sign_exponent:16;
+ unsigned int empty:16;
+ } parts;
+} ieee_long_double_shape_type;
+
+#endif
+
+/* Get three 32 bit ints from a double. */
+
+#define GET_LDOUBLE_WORDS(exp,ix0,ix1,d) \
+do { \
+ ieee_long_double_shape_type ew_u; \
+ ew_u.value = (d); \
+ (exp) = ew_u.parts.sign_exponent; \
+ (ix0) = ew_u.parts.msw; \
+ (ix1) = ew_u.parts.lsw; \
+} while (0)
+
+/* Set a double from two 32 bit ints. */
+
+#define SET_LDOUBLE_WORDS(d,exp,ix0,ix1) \
+do { \
+ ieee_long_double_shape_type iw_u; \
+ iw_u.parts.sign_exponent = (exp); \
+ iw_u.parts.msw = (ix0); \
+ iw_u.parts.lsw = (ix1); \
+ (d) = iw_u.value; \
+} while (0)
+
+/* Set the more significant 32 bits of a long double mantissa from an int. */
+
+#define SET_LDOUBLE_MSW(d,v) \
+do { \
+ ieee_long_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+/* Get int from the exponent of a long double. */
+
+#define GET_LDOUBLE_EXP(exp,d) \
+do { \
+ ieee_long_double_shape_type ge_u; \
+ ge_u.value = (d);
+ (exp) = ge_u.parts.sign_exponent; \
+} while (0)
+
+/* Set exponent of a long double from an int. */
+
+#define SET_LDOUBLE_EXP(d,exp) \
+do { \
+ ieee_long_double_shape_type se_u; \
+ se_u.value = (d); \
+ se_u.parts.sign_exponent = (exp); \
+ (d) = se_u.value; \
+} while (0)
+
+
/* ieee style elementary functions */
extern double __ieee754_sqrt __P((double));
extern double __ieee754_acos __P((double));
@@ -219,4 +306,41 @@ extern float __kernel_cosf __P((float,float));
extern float __kernel_tanf __P((float,float,int));
extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int*));
+
+/* ieee style elementary long double functions */
+extern long double __ieee754_sqrtl __P((long double));
+extern long double __ieee754_acosl __P((long double));
+extern long double __ieee754_acoshl __P((long double));
+extern long double __ieee754_logl __P((long double));
+extern long double __ieee754_atanhl __P((long double));
+extern long double __ieee754_asinl __P((long double));
+extern long double __ieee754_atan2l __P((long double,long double));
+extern long double __ieee754_expl __P((long double));
+extern long double __ieee754_coshl __P((long double));
+extern long double __ieee754_fmodl __P((long double,long double));
+extern long double __ieee754_powl __P((long double,long double));
+extern long double __ieee754_lgammal_r __P((long double,int *));
+extern long double __ieee754_gammal_r __P((long double,int *));
+extern long double __ieee754_lgammal __P((long double));
+extern long double __ieee754_gammal __P((long double));
+extern long double __ieee754_log10l __P((long double));
+extern long double __ieee754_sinhl __P((long double));
+extern long double __ieee754_hypotl __P((long double,long double));
+extern long double __ieee754_j0l __P((long double));
+extern long double __ieee754_j1l __P((long double));
+extern long double __ieee754_y0l __P((long double));
+extern long double __ieee754_y1l __P((long double));
+extern long double __ieee754_jnl __P((int,long double));
+extern long double __ieee754_ynl __P((int,long double));
+extern long double __ieee754_remainderl __P((long double,long double));
+extern int __ieee754_rem_pio2l __P((long double,long double*));
+extern long double __ieee754_scalbl __P((long double,long double));
+
+/* long double versions of fdlibm kernel functions */
+extern long double __kernel_sinl __P((long double,long double,int));
+extern long double __kernel_cosl __P((long double,long double));
+extern long double __kernel_tanl __P((long double,long double,int));
+extern int __kernel_rem_pio2l __P((long double*,long double*,int,int,
+ int,const int*));
+
#endif /* _MATH_PRIVATE_H_ */