Back to index

glibc  2.9
mathinline.h
Go to the documentation of this file.
00001 /* Definitions of inline math functions implemented by the m68881/2.
00002    Copyright (C) 1991,92,93,94,96,97,98,99,2000,2002, 2003, 2004, 2008
00003      Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef _MATH_H
00022 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
00023 #endif
00024 
00025 #ifndef __extern_inline
00026 # define __MATH_INLINE __inline
00027 #else
00028 # define __MATH_INLINE __extern_inline
00029 #endif
00030 
00031 #ifdef __GNUC__
00032 
00033 #ifdef __USE_ISOC99
00034 /* GCC 3.1 and up have builtins that actually can be used.  */
00035 # if !__GNUC_PREREQ (3,1)
00036 /* ISO C99 defines some macros to perform unordered comparisons.  The
00037    m68k FPU supports this with special opcodes and we should use them.
00038    These must not be inline functions since we have to be able to handle
00039    all floating-point types.  */
00040 #  undef isgreater
00041 #  undef isgreaterequal
00042 #  undef isless
00043 #  undef islessequal
00044 #  undef islessgreater
00045 #  undef isunordered
00046 #  define isgreater(x, y)                               \
00047    __extension__                                 \
00048    ({ char __result;                             \
00049       __asm__ ("fcmp%.x %2,%1; fsogt %0"         \
00050               : "=dm" (__result) : "f" (x), "f" (y));   \
00051       __result != 0; })
00052 
00053 #  define isgreaterequal(x, y)                          \
00054    __extension__                                 \
00055    ({ char __result;                             \
00056       __asm__ ("fcmp%.x %2,%1; fsoge %0"         \
00057               : "=dm" (__result) : "f" (x), "f" (y));   \
00058       __result != 0; })
00059 
00060 #  define isless(x, y)                                  \
00061    __extension__                                 \
00062    ({ char __result;                             \
00063       __asm__ ("fcmp%.x %2,%1; fsolt %0"         \
00064               : "=dm" (__result) : "f" (x), "f" (y));   \
00065       __result != 0; })
00066 
00067 #  define islessequal(x, y)                      \
00068    __extension__                                 \
00069    ({ char __result;                             \
00070       __asm__ ("fcmp%.x %2,%1; fsole %0"         \
00071               : "=dm" (__result) : "f" (x), "f" (y));   \
00072       __result != 0; })
00073 
00074 #  define islessgreater(x, y)                           \
00075    __extension__                                 \
00076    ({ char __result;                             \
00077       __asm__ ("fcmp%.x %2,%1; fsogl %0"         \
00078               : "=dm" (__result) : "f" (x), "f" (y));   \
00079       __result != 0; })
00080 
00081 #  define isunordered(x, y)                      \
00082    __extension__                                 \
00083    ({ char __result;                             \
00084       __asm__ ("fcmp%.x %2,%1; fsun %0"                 \
00085               : "=dm" (__result) : "f" (x), "f" (y));   \
00086       __result != 0; })
00087 # endif /* GCC 3.1 */
00088 #endif
00089 
00090 
00091 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
00092     || defined __LIBC_INTERNAL_MATH_INLINES
00093 
00094 #ifdef __LIBC_INTERNAL_MATH_INLINES
00095 /* This is used when defining the functions themselves.  Define them with
00096    __ names, and with `static inline' instead of `extern inline' so the
00097    bodies will always be used, never an external function call.  */
00098 # define __m81_u(x)         __CONCAT(__,x)
00099 # define __m81_inline              static __inline
00100 #else
00101 # define __m81_u(x)         x
00102 # define __m81_inline __MATH_INLINE
00103 # define __M81_MATH_INLINES 1
00104 #endif
00105 
00106 /* Define a const math function.  */
00107 #define __m81_defun(rettype, func, args)                             \
00108   __m81_inline rettype __attribute__((__const__))                           \
00109   __m81_u(func) args
00110 
00111 /* Define the three variants of a math function that has a direct
00112    implementation in the m68k fpu.  FUNC is the name for C (which will be
00113    suffixed with f and l for the float and long double version, resp).  OP
00114    is the name of the fpu operation (without leading f).  */
00115 
00116 #if defined __USE_MISC || defined __USE_ISOC99
00117 # define __inline_mathop(func, op)               \
00118   __inline_mathop1(double, func, op)                    \
00119   __inline_mathop1(float, __CONCAT(func,f), op)  \
00120   __inline_mathop1(long double, __CONCAT(func,l), op)
00121 #else
00122 # define __inline_mathop(func, op)               \
00123   __inline_mathop1(double, func, op)
00124 #endif
00125 
00126 #define __inline_mathop1(float_type,func, op)                               \
00127   __m81_defun (float_type, func, (float_type __mathop_x))                   \
00128   {                                                                  \
00129     float_type __result;                                             \
00130     __asm("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
00131     return __result;                                                 \
00132   }
00133 
00134 __inline_mathop(__atan, atan)
00135 __inline_mathop(__cos, cos)
00136 __inline_mathop(__sin, sin)
00137 __inline_mathop(__tan, tan)
00138 __inline_mathop(__tanh, tanh)
00139 __inline_mathop(__fabs, abs)
00140 
00141 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
00142 __inline_mathop(__rint, int)
00143 __inline_mathop(__expm1, etoxm1)
00144 __inline_mathop(__log1p, lognp1)
00145 #endif
00146 
00147 #ifdef __USE_MISC
00148 __inline_mathop(__significand, getman)
00149 #endif
00150 
00151 #ifdef __USE_ISOC99
00152 __inline_mathop(__trunc, intrz)
00153 #endif
00154 
00155 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
00156 
00157 __inline_mathop(atan, atan)
00158 __inline_mathop(cos, cos)
00159 __inline_mathop(sin, sin)
00160 __inline_mathop(tan, tan)
00161 __inline_mathop(tanh, tanh)
00162 
00163 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
00164 __inline_mathop(rint, int)
00165 __inline_mathop(expm1, etoxm1)
00166 __inline_mathop(log1p, lognp1)
00167 # endif
00168 
00169 # ifdef __USE_MISC
00170 __inline_mathop(significand, getman)
00171 # endif
00172 
00173 # ifdef __USE_ISOC99
00174 __inline_mathop(trunc, intrz)
00175 # endif
00176 
00177 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
00178 
00179 /* This macro contains the definition for the rest of the inline
00180    functions, using FLOAT_TYPE as the domain type and S as the suffix
00181    for the function names.  */
00182 
00183 #define __inline_functions(float_type, s)                        \
00184 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x))         \
00185 {                                                                \
00186   float_type __result;                                                  \
00187   unsigned long int __ctrl_reg;                                         \
00188   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));          \
00189   /* Set rounding towards negative infinity.  */                 \
00190   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
00191                     : "dmi" ((__ctrl_reg & ~0x10) | 0x20));             \
00192   /* Convert X to an integer, using -Inf rounding.  */                  \
00193   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));         \
00194   /* Restore the previous rounding mode.  */                            \
00195   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
00196                     : "dmi" (__ctrl_reg));                              \
00197   return __result;                                               \
00198 }                                                                \
00199                                                                  \
00200 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x))          \
00201 {                                                                \
00202   float_type __result;                                                  \
00203   unsigned long int __ctrl_reg;                                         \
00204   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));          \
00205   /* Set rounding towards positive infinity.  */                 \
00206   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
00207                     : "dmi" (__ctrl_reg | 0x30));                       \
00208   /* Convert X to an integer, using +Inf rounding.  */                  \
00209   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));         \
00210   /* Restore the previous rounding mode.  */                            \
00211   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
00212                     : "dmi" (__ctrl_reg));                              \
00213   return __result;                                               \
00214 }
00215 
00216 __inline_functions(double,)
00217 #if defined __USE_MISC || defined __USE_ISOC99
00218 __inline_functions(float,f)
00219 __inline_functions(long double,l)
00220 #endif
00221 #undef __inline_functions
00222 
00223 #ifdef __USE_MISC
00224 
00225 # define __inline_functions(float_type, s)                              \
00226 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value))            \
00227 {                                                                \
00228   /* There is no branch-condition for infinity,                         \
00229      so we must extract and examine the condition codes manually.  */   \
00230   unsigned long int __fpsr;                                      \
00231   __asm("ftst%.x %1\n"                                                  \
00232        "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
00233   return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;      \
00234 }                                                                \
00235                                                                  \
00236 __m81_defun (int, __CONCAT(__finite,s), (float_type __value))           \
00237 {                                                                \
00238   /* There is no branch-condition for infinity, so we must extract and         \
00239      examine the condition codes manually.  */                          \
00240   unsigned long int __fpsr;                                      \
00241   __asm ("ftst%.x %1\n"                                                 \
00242         "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));        \
00243   return (__fpsr & (3 << 24)) == 0;                                     \
00244 }                                                                \
00245                                                                  \
00246 __m81_defun (float_type, __CONCAT(__scalbn,s),                          \
00247             (float_type __x, int __n))                                  \
00248 {                                                                \
00249   float_type __result;                                                  \
00250   __asm ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x));  \
00251   return __result;                                               \
00252 }
00253 
00254 __inline_functions(double,)
00255 __inline_functions(float,f)
00256 __inline_functions(long double,l)
00257 # undef __inline_functions
00258 
00259 #endif /* Use misc.  */
00260 
00261 #if defined __USE_MISC || defined __USE_XOPEN
00262 
00263 # define __inline_functions(float_type, s)                              \
00264 __m81_defun (int, __CONCAT(__isnan,s), (float_type __value))            \
00265 {                                                                \
00266   char __result;                                                 \
00267   __asm("ftst%.x %1\n"                                                  \
00268        "fsun %0" : "=dm" (__result) : "f" (__value));                   \
00269   return __result;                                               \
00270 }
00271 
00272 __inline_functions(double,)
00273 # ifdef __USE_MISC
00274 __inline_functions(float,f)
00275 __inline_functions(long double,l)
00276 # endif
00277 # undef __inline_functions
00278 
00279 #endif
00280 
00281 #ifdef __USE_ISOC99
00282 
00283 # define __inline_functions(float_type, s)                              \
00284 __m81_defun (int, __CONCAT(__signbit,s), (float_type __value))          \
00285 {                                                                \
00286   /* There is no branch-condition for the sign bit, so we must extract         \
00287      and examine the condition codes manually.  */                      \
00288   unsigned long int __fpsr;                                      \
00289   __asm ("ftst%.x %1\n"                                                 \
00290         "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));        \
00291   return (__fpsr >> 27) & 1;                                            \
00292 }                                                                \
00293                                                                  \
00294   __m81_defun (float_type, __CONCAT(__scalbln,s),                       \
00295             (float_type __x, long int __n))                             \
00296 {                                                                \
00297   return __CONCAT(__scalbn,s) (__x, __n);                        \
00298 }                                                                \
00299                                                                  \
00300 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x))     \
00301 {                                                                \
00302   float_type __result;                                                  \
00303   unsigned long int __ctrl_reg;                                         \
00304   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));          \
00305   /* Temporarily disable the inexact exception.  */                     \
00306   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
00307                     : "dmi" (__ctrl_reg & ~0x200));                     \
00308   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));         \
00309   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
00310                     : "dmi" (__ctrl_reg));                              \
00311   return __result;                                               \
00312 }                                                                \
00313                                                                  \
00314 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x))           \
00315 {                                                                \
00316   long int __result;                                             \
00317   __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));             \
00318   return __result;                                               \
00319 }                                                                \
00320                                                                  \
00321 __m81_inline float_type                                                 \
00322 __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y,              \
00323                         float_type __z)                          \
00324 {                                                                \
00325   return (__x * __y) + __z;                                      \
00326 }
00327 
00328 __inline_functions (double,)
00329 __inline_functions (float,f)
00330 __inline_functions (long double,l)
00331 # undef __inline_functions
00332 
00333 #endif /* Use ISO C9x */
00334 
00335 #ifdef __USE_GNU
00336 
00337 # define __inline_functions(float_type, s)                            \
00338 __m81_inline void                                              \
00339 __m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx,     \
00340                            float_type *__cosx)                 \
00341 {                                                              \
00342   __asm ("fsincos%.x %2,%1:%0"                                        \
00343         : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));                \
00344 }
00345 
00346 __inline_functions (double,)
00347 __inline_functions (float,f)
00348 __inline_functions (long double,l)
00349 # undef __inline_functions
00350 
00351 #endif
00352 
00353 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
00354 
00355 /* Define inline versions of the user visible functions.  */
00356 
00357 /* Note that there must be no whitespace before the argument passed for
00358    NAME, to make token pasting work correctly with -traditional.  */
00359 # define __inline_forward_c(rettype, name, args1, args2)       \
00360 __MATH_INLINE rettype __attribute__((__const__))        \
00361   name args1                                            \
00362 {                                                       \
00363   return __CONCAT(__,name) args2;                       \
00364 }
00365 
00366 # define __inline_forward(rettype, name, args1, args2)  \
00367 __MATH_INLINE rettype name args1                 \
00368 {                                                \
00369   return __CONCAT(__,name) args2;                \
00370 }
00371 
00372 __inline_forward_c(double,floor, (double __x), (__x))
00373 __inline_forward_c(double,ceil, (double __x), (__x))
00374 # ifdef __USE_MISC
00375 #  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
00376 __inline_forward_c(int,isinf, (double __value), (__value))
00377 #  endif
00378 __inline_forward_c(int,finite, (double __value), (__value))
00379 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
00380 # endif
00381 # if defined __USE_MISC || defined __USE_XOPEN
00382 #  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
00383 __inline_forward_c(int,isnan, (double __value), (__value))
00384 #  endif
00385 # endif
00386 # ifdef __USE_ISOC99
00387 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
00388 __inline_forward_c(double,nearbyint, (double __value), (__value))
00389 __inline_forward_c(long int,lrint, (double __value), (__value))
00390 __inline_forward_c(double,fma, (double __x, double __y, double __z),
00391                  (__x, __y, __z))
00392 # endif
00393 # ifdef __USE_GNU
00394 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
00395                (__x, __sinx, __cosx))
00396 # endif
00397 
00398 # if defined __USE_MISC || defined __USE_ISOC99
00399 
00400 __inline_forward_c(float,floorf, (float __x), (__x))
00401 __inline_forward_c(float,ceilf, (float __x), (__x))
00402 #  ifdef __USE_MISC
00403 __inline_forward_c(int,isinff, (float __value), (__value))
00404 __inline_forward_c(int,finitef, (float __value), (__value))
00405 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
00406 __inline_forward_c(int,isnanf, (float __value), (__value))
00407 #  endif
00408 # ifdef __USE_ISOC99
00409 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
00410 __inline_forward_c(float,nearbyintf, (float __value), (__value))
00411 __inline_forward_c(long int,lrintf, (float __value), (__value))
00412 __inline_forward_c(float,fmaf, (float __x, float __y, float __z),
00413                  (__x, __y, __z))
00414 # endif
00415 # ifdef __USE_GNU
00416 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
00417                (__x, __sinx, __cosx))
00418 # endif
00419 
00420 __inline_forward_c(long double,floorl, (long double __x), (__x))
00421 __inline_forward_c(long double,ceill, (long double __x), (__x))
00422 # ifdef __USE_MISC
00423 __inline_forward_c(int,isinfl, (long double __value), (__value))
00424 __inline_forward_c(int,finitel, (long double __value), (__value))
00425 __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
00426 __inline_forward_c(int,isnanl, (long double __value), (__value))
00427 # endif
00428 # ifdef __USE_ISOC99
00429 __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
00430                  (__x, __n))
00431 __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
00432 __inline_forward_c(long int,lrintl, (long double __value), (__value))
00433 __inline_forward_c(long double,fmal,
00434                  (long double __x, long double __y, long double __z),
00435                  (__x, __y, __z))
00436 # endif
00437 # ifdef __USE_GNU
00438 __inline_forward(void,sincosl,
00439                (long double __x, long double *__sinx, long double *__cosx),
00440                (__x, __sinx, __cosx))
00441 # endif
00442 
00443 #endif /* Use misc or ISO C99 */
00444 
00445 #undef __inline_forward
00446 #undef __inline_forward_c
00447 
00448 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
00449 
00450 #endif
00451 #endif /* GCC.  */