src/libm/math_private.h
author Daniel Wyatt <Daniel.Wyatt@gmail.com>
Tue, 16 Nov 2010 13:24:55 -0500
changeset 4909 fd40b483d489
parent 2760 02aa80d7905f
child 5086 c2539ff054c8
permissions -rw-r--r--
Use SDL endian macros in libm.
This fixes problems (specifically with SDL_floor) for systems where __BYTE_ORDER is not defined.
     1 /*
     2  * ====================================================
     3  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
     4  *
     5  * Developed at SunPro, a Sun Microsystems, Inc. business.
     6  * Permission to use, copy, modify, and distribute this
     7  * software is freely granted, provided that this notice
     8  * is preserved.
     9  * ====================================================
    10  */
    11 
    12 /*
    13  * from: @(#)fdlibm.h 5.1 93/09/24
    14  * $Id: math_private.h,v 1.3 2004/02/09 07:10:38 andersen Exp $
    15  */
    16 
    17 #ifndef _MATH_PRIVATE_H_
    18 #define _MATH_PRIVATE_H_
    19 
    20 /*#include <endian.h>*/
    21 #include "SDL_endian.h"
    22 #include <sys/types.h>
    23 
    24 #define attribute_hidden
    25 #define libm_hidden_proto(x)
    26 #define libm_hidden_def(x)
    27 
    28 typedef unsigned int u_int32_t;
    29 
    30 /* The original fdlibm code used statements like:
    31 	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
    32 	ix0 = *(n0+(int*)&x);			* high word of x *
    33 	ix1 = *((1-n0)+(int*)&x);		* low word of x *
    34    to dig two 32 bit words out of the 64 bit IEEE floating point
    35    value.  That is non-ANSI, and, moreover, the gcc instruction
    36    scheduler gets it wrong.  We instead use the following macros.
    37    Unlike the original code, we determine the endianness at compile
    38    time, not at run time; I don't see much benefit to selecting
    39    endianness at run time.  */
    40 
    41 /* A union which permits us to convert between a double and two 32 bit
    42    ints.  */
    43 
    44 /*
    45  * Math on arm is special:
    46  * For FPA, float words are always big-endian.
    47  * For VFP, floats words follow the memory system mode.
    48  */
    49 
    50 #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
    51 
    52 typedef union
    53 {
    54     double value;
    55     struct
    56     {
    57         u_int32_t msw;
    58         u_int32_t lsw;
    59     } parts;
    60 } ieee_double_shape_type;
    61 
    62 #else
    63 
    64 typedef union
    65 {
    66     double value;
    67     struct
    68     {
    69         u_int32_t lsw;
    70         u_int32_t msw;
    71     } parts;
    72 } ieee_double_shape_type;
    73 
    74 #endif
    75 
    76 /* Get two 32 bit ints from a double.  */
    77 
    78 #define EXTRACT_WORDS(ix0,ix1,d)				\
    79 do {								\
    80   ieee_double_shape_type ew_u;					\
    81   ew_u.value = (d);						\
    82   (ix0) = ew_u.parts.msw;					\
    83   (ix1) = ew_u.parts.lsw;					\
    84 } while (0)
    85 
    86 /* Get the more significant 32 bit int from a double.  */
    87 
    88 #define GET_HIGH_WORD(i,d)					\
    89 do {								\
    90   ieee_double_shape_type gh_u;					\
    91   gh_u.value = (d);						\
    92   (i) = gh_u.parts.msw;						\
    93 } while (0)
    94 
    95 /* Get the less significant 32 bit int from a double.  */
    96 
    97 #define GET_LOW_WORD(i,d)					\
    98 do {								\
    99   ieee_double_shape_type gl_u;					\
   100   gl_u.value = (d);						\
   101   (i) = gl_u.parts.lsw;						\
   102 } while (0)
   103 
   104 /* Set a double from two 32 bit ints.  */
   105 
   106 #define INSERT_WORDS(d,ix0,ix1)					\
   107 do {								\
   108   ieee_double_shape_type iw_u;					\
   109   iw_u.parts.msw = (ix0);					\
   110   iw_u.parts.lsw = (ix1);					\
   111   (d) = iw_u.value;						\
   112 } while (0)
   113 
   114 /* Set the more significant 32 bits of a double from an int.  */
   115 
   116 #define SET_HIGH_WORD(d,v)					\
   117 do {								\
   118   ieee_double_shape_type sh_u;					\
   119   sh_u.value = (d);						\
   120   sh_u.parts.msw = (v);						\
   121   (d) = sh_u.value;						\
   122 } while (0)
   123 
   124 /* Set the less significant 32 bits of a double from an int.  */
   125 
   126 #define SET_LOW_WORD(d,v)					\
   127 do {								\
   128   ieee_double_shape_type sl_u;					\
   129   sl_u.value = (d);						\
   130   sl_u.parts.lsw = (v);						\
   131   (d) = sl_u.value;						\
   132 } while (0)
   133 
   134 /* A union which permits us to convert between a float and a 32 bit
   135    int.  */
   136 
   137 typedef union
   138 {
   139     float value;
   140     u_int32_t word;
   141 } ieee_float_shape_type;
   142 
   143 /* Get a 32 bit int from a float.  */
   144 
   145 #define GET_FLOAT_WORD(i,d)					\
   146 do {								\
   147   ieee_float_shape_type gf_u;					\
   148   gf_u.value = (d);						\
   149   (i) = gf_u.word;						\
   150 } while (0)
   151 
   152 /* Set a float from a 32 bit int.  */
   153 
   154 #define SET_FLOAT_WORD(d,i)					\
   155 do {								\
   156   ieee_float_shape_type sf_u;					\
   157   sf_u.word = (i);						\
   158   (d) = sf_u.value;						\
   159 } while (0)
   160 
   161 /* ieee style elementary functions */
   162 extern double
   163 __ieee754_sqrt(double)
   164     attribute_hidden;
   165      extern double __ieee754_acos(double) attribute_hidden;
   166      extern double __ieee754_acosh(double) attribute_hidden;
   167      extern double __ieee754_log(double) attribute_hidden;
   168      extern double __ieee754_atanh(double) attribute_hidden;
   169      extern double __ieee754_asin(double) attribute_hidden;
   170      extern double __ieee754_atan2(double, double) attribute_hidden;
   171      extern double __ieee754_exp(double) attribute_hidden;
   172      extern double __ieee754_cosh(double) attribute_hidden;
   173      extern double __ieee754_fmod(double, double) attribute_hidden;
   174      extern double __ieee754_pow(double, double) attribute_hidden;
   175      extern double __ieee754_lgamma_r(double, int *) attribute_hidden;
   176      extern double __ieee754_gamma_r(double, int *) attribute_hidden;
   177      extern double __ieee754_lgamma(double) attribute_hidden;
   178      extern double __ieee754_gamma(double) attribute_hidden;
   179      extern double __ieee754_log10(double) attribute_hidden;
   180      extern double __ieee754_sinh(double) attribute_hidden;
   181      extern double __ieee754_hypot(double, double) attribute_hidden;
   182      extern double __ieee754_j0(double) attribute_hidden;
   183      extern double __ieee754_j1(double) attribute_hidden;
   184      extern double __ieee754_y0(double) attribute_hidden;
   185      extern double __ieee754_y1(double) attribute_hidden;
   186      extern double __ieee754_jn(int, double) attribute_hidden;
   187      extern double __ieee754_yn(int, double) attribute_hidden;
   188      extern double __ieee754_remainder(double, double) attribute_hidden;
   189      extern int __ieee754_rem_pio2(double, double *) attribute_hidden;
   190 #if defined(_SCALB_INT)
   191      extern double __ieee754_scalb(double, int) attribute_hidden;
   192 #else
   193      extern double __ieee754_scalb(double, double) attribute_hidden;
   194 #endif
   195 
   196 /* fdlibm kernel function */
   197 #ifndef _IEEE_LIBM
   198      extern double __kernel_standard(double, double, int) attribute_hidden;
   199 #endif
   200      extern double __kernel_sin(double, double, int) attribute_hidden;
   201      extern double __kernel_cos(double, double) attribute_hidden;
   202      extern double __kernel_tan(double, double, int) attribute_hidden;
   203      extern int __kernel_rem_pio2(double *, double *, int, int, int,
   204                                   const int *) attribute_hidden;
   205 
   206 #endif /* _MATH_PRIVATE_H_ */