diff --git a/newlib/libc/include/machine/ieeefp.h b/newlib/libc/include/machine/ieeefp.h index 29c08fa43..b1b44665e 100644 --- a/newlib/libc/include/machine/ieeefp.h +++ b/newlib/libc/include/machine/ieeefp.h @@ -48,6 +48,23 @@ This represents what type a float arg is passed as. It is used when the type is not promoted to double. + + __OBSOLETE_MATH_DEFAULT + + Default value for __OBSOLETE_MATH if that's not set by the user. + It should be set here based on predefined feature macros. + + __OBSOLETE_MATH + + If set to 1 then some new math code will be disabled and older libm + code will be used instead. This is necessary because the new math + code does not support all targets, it assumes that the toolchain has + ISO C99 support (hexfloat literals, standard fenv semantics), the + target has IEEE-754 conforming binary32 float and binary64 double + (not mixed endian) representation, standard SNaN representation, + double and single precision arithmetics has similar latency and it + has no legacy SVID matherr support, only POSIX errno and fenv + exception based error handling. */ #if (defined(__arm__) || defined(__thumb__)) && !defined(__MAVERICK__) @@ -61,6 +78,7 @@ # else # define __IEEE_BIG_ENDIAN # endif +# define __OBSOLETE_MATH_DEFAULT 0 #else # define __IEEE_BIG_ENDIAN # ifdef __ARMEL__ @@ -75,6 +93,7 @@ #else #define __IEEE_BIG_ENDIAN #endif +#define __OBSOLETE_MATH_DEFAULT 0 #endif #ifdef __epiphany__ @@ -427,6 +446,14 @@ #define __IEEE_BIG_ENDIAN #endif +#ifndef __OBSOLETE_MATH_DEFAULT +/* Use old math code by default. */ +#define __OBSOLETE_MATH_DEFAULT 1 +#endif +#ifndef __OBSOLETE_MATH +#define __OBSOLETE_MATH __OBSOLETE_MATH_DEFAULT +#endif + #ifndef __IEEE_BIG_ENDIAN #ifndef __IEEE_LITTLE_ENDIAN #error Endianess not declared!! diff --git a/newlib/libm/common/Makefile.am b/newlib/libm/common/Makefile.am index 1268e17db..3e2620c7e 100644 --- a/newlib/libm/common/Makefile.am +++ b/newlib/libm/common/Makefile.am @@ -18,11 +18,14 @@ fsrc = sf_finite.c sf_copysign.c sf_modf.c sf_scalbn.c \ sf_cbrt.c sf_exp10.c sf_expm1.c sf_ilogb.c \ sf_infinity.c sf_isinf.c sf_isinff.c sf_isnan.c sf_isnanf.c \ sf_log1p.c sf_nan.c sf_nextafter.c sf_pow10.c \ - sf_rint.c sf_logb.c sf_log2.c \ + sf_rint.c sf_logb.c \ sf_fdim.c sf_fma.c sf_fmax.c sf_fmin.c sf_fpclassify.c \ sf_lrint.c sf_llrint.c \ sf_lround.c sf_llround.c sf_nearbyint.c sf_remquo.c sf_round.c \ - sf_scalbln.c sf_trunc.c + sf_scalbln.c sf_trunc.c \ + sf_exp.c sf_exp2.c sf_exp2_data.c sf_log.c sf_log_data.c \ + sf_log2.c sf_log2_data.c sf_pow_log2_data.c sf_pow.c \ + math_errf.c lsrc = atanl.c cosl.c sinl.c tanl.c tanhl.c frexpl.c modfl.c ceill.c fabsl.c \ floorl.c log1pl.c expm1l.c acosl.c asinl.c atan2l.c coshl.c sinhl.c \ diff --git a/newlib/libm/common/Makefile.in b/newlib/libm/common/Makefile.in index 9b367653d..c603be361 100644 --- a/newlib/libm/common/Makefile.in +++ b/newlib/libm/common/Makefile.in @@ -78,21 +78,21 @@ am__objects_1 = lib_a-s_finite.$(OBJEXT) lib_a-s_copysign.$(OBJEXT) \ lib_a-s_modf.$(OBJEXT) lib_a-s_scalbn.$(OBJEXT) \ lib_a-s_cbrt.$(OBJEXT) lib_a-s_exp10.$(OBJEXT) \ lib_a-s_expm1.$(OBJEXT) lib_a-s_ilogb.$(OBJEXT) \ - lib_a-s_infinity.$(OBJEXT) \ - lib_a-s_isinf.$(OBJEXT) lib_a-s_isinfd.$(OBJEXT) \ - lib_a-s_isnan.$(OBJEXT) lib_a-s_isnand.$(OBJEXT) \ - lib_a-s_log1p.$(OBJEXT) lib_a-s_nan.$(OBJEXT) \ - lib_a-s_nextafter.$(OBJEXT) lib_a-s_pow10.$(OBJEXT) \ - lib_a-s_rint.$(OBJEXT) lib_a-s_logb.$(OBJEXT) \ - lib_a-s_log2.$(OBJEXT) lib_a-s_matherr.$(OBJEXT) \ - lib_a-s_lib_ver.$(OBJEXT) lib_a-s_fdim.$(OBJEXT) \ - lib_a-s_fma.$(OBJEXT) lib_a-s_fmax.$(OBJEXT) \ - lib_a-s_fmin.$(OBJEXT) lib_a-s_fpclassify.$(OBJEXT) \ - lib_a-s_lrint.$(OBJEXT) lib_a-s_llrint.$(OBJEXT) \ - lib_a-s_lround.$(OBJEXT) lib_a-s_llround.$(OBJEXT) \ - lib_a-s_nearbyint.$(OBJEXT) lib_a-s_remquo.$(OBJEXT) \ - lib_a-s_round.$(OBJEXT) lib_a-s_scalbln.$(OBJEXT) \ - lib_a-s_signbit.$(OBJEXT) lib_a-s_trunc.$(OBJEXT) + lib_a-s_infinity.$(OBJEXT) lib_a-s_isinf.$(OBJEXT) \ + lib_a-s_isinfd.$(OBJEXT) lib_a-s_isnan.$(OBJEXT) \ + lib_a-s_isnand.$(OBJEXT) lib_a-s_log1p.$(OBJEXT) \ + lib_a-s_nan.$(OBJEXT) lib_a-s_nextafter.$(OBJEXT) \ + lib_a-s_pow10.$(OBJEXT) lib_a-s_rint.$(OBJEXT) \ + lib_a-s_logb.$(OBJEXT) lib_a-s_log2.$(OBJEXT) \ + lib_a-s_matherr.$(OBJEXT) lib_a-s_lib_ver.$(OBJEXT) \ + lib_a-s_fdim.$(OBJEXT) lib_a-s_fma.$(OBJEXT) \ + lib_a-s_fmax.$(OBJEXT) lib_a-s_fmin.$(OBJEXT) \ + lib_a-s_fpclassify.$(OBJEXT) lib_a-s_lrint.$(OBJEXT) \ + lib_a-s_llrint.$(OBJEXT) lib_a-s_lround.$(OBJEXT) \ + lib_a-s_llround.$(OBJEXT) lib_a-s_nearbyint.$(OBJEXT) \ + lib_a-s_remquo.$(OBJEXT) lib_a-s_round.$(OBJEXT) \ + lib_a-s_scalbln.$(OBJEXT) lib_a-s_signbit.$(OBJEXT) \ + lib_a-s_trunc.$(OBJEXT) am__objects_2 = lib_a-sf_finite.$(OBJEXT) lib_a-sf_copysign.$(OBJEXT) \ lib_a-sf_modf.$(OBJEXT) lib_a-sf_scalbn.$(OBJEXT) \ lib_a-sf_cbrt.$(OBJEXT) lib_a-sf_exp10.$(OBJEXT) \ @@ -102,14 +102,19 @@ am__objects_2 = lib_a-sf_finite.$(OBJEXT) lib_a-sf_copysign.$(OBJEXT) \ lib_a-sf_isnanf.$(OBJEXT) lib_a-sf_log1p.$(OBJEXT) \ lib_a-sf_nan.$(OBJEXT) lib_a-sf_nextafter.$(OBJEXT) \ lib_a-sf_pow10.$(OBJEXT) lib_a-sf_rint.$(OBJEXT) \ - lib_a-sf_logb.$(OBJEXT) lib_a-sf_log2.$(OBJEXT) \ - lib_a-sf_fdim.$(OBJEXT) lib_a-sf_fma.$(OBJEXT) \ - lib_a-sf_fmax.$(OBJEXT) lib_a-sf_fmin.$(OBJEXT) \ - lib_a-sf_fpclassify.$(OBJEXT) lib_a-sf_lrint.$(OBJEXT) \ - lib_a-sf_llrint.$(OBJEXT) lib_a-sf_lround.$(OBJEXT) \ - lib_a-sf_llround.$(OBJEXT) lib_a-sf_nearbyint.$(OBJEXT) \ - lib_a-sf_remquo.$(OBJEXT) lib_a-sf_round.$(OBJEXT) \ - lib_a-sf_scalbln.$(OBJEXT) lib_a-sf_trunc.$(OBJEXT) + lib_a-sf_logb.$(OBJEXT) lib_a-sf_fdim.$(OBJEXT) \ + lib_a-sf_fma.$(OBJEXT) lib_a-sf_fmax.$(OBJEXT) \ + lib_a-sf_fmin.$(OBJEXT) lib_a-sf_fpclassify.$(OBJEXT) \ + lib_a-sf_lrint.$(OBJEXT) lib_a-sf_llrint.$(OBJEXT) \ + lib_a-sf_lround.$(OBJEXT) lib_a-sf_llround.$(OBJEXT) \ + lib_a-sf_nearbyint.$(OBJEXT) lib_a-sf_remquo.$(OBJEXT) \ + lib_a-sf_round.$(OBJEXT) lib_a-sf_scalbln.$(OBJEXT) \ + lib_a-sf_trunc.$(OBJEXT) lib_a-sf_exp.$(OBJEXT) \ + lib_a-sf_exp2.$(OBJEXT) lib_a-sf_exp2_data.$(OBJEXT) \ + lib_a-sf_log.$(OBJEXT) lib_a-sf_log_data.$(OBJEXT) \ + lib_a-sf_log2.$(OBJEXT) lib_a-sf_log2_data.$(OBJEXT) \ + lib_a-sf_pow_log2_data.$(OBJEXT) lib_a-sf_pow.$(OBJEXT) \ + lib_a-math_errf.$(OBJEXT) am__objects_3 = lib_a-atanl.$(OBJEXT) lib_a-cosl.$(OBJEXT) \ lib_a-sinl.$(OBJEXT) lib_a-tanl.$(OBJEXT) \ lib_a-tanhl.$(OBJEXT) lib_a-frexpl.$(OBJEXT) \ @@ -148,21 +153,23 @@ lib_a_OBJECTS = $(am_lib_a_OBJECTS) LTLIBRARIES = $(noinst_LTLIBRARIES) libcommon_la_LIBADD = am__objects_5 = s_finite.lo s_copysign.lo s_modf.lo s_scalbn.lo \ - s_cbrt.lo s_exp10.lo s_expm1.lo s_ilogb.lo \ - s_infinity.lo s_isinf.lo s_isinfd.lo s_isnan.lo s_isnand.lo \ - s_log1p.lo s_nan.lo s_nextafter.lo s_pow10.lo s_rint.lo \ - s_logb.lo s_log2.lo s_matherr.lo s_lib_ver.lo s_fdim.lo \ - s_fma.lo s_fmax.lo s_fmin.lo s_fpclassify.lo s_lrint.lo \ - s_llrint.lo s_lround.lo s_llround.lo s_nearbyint.lo \ - s_remquo.lo s_round.lo s_scalbln.lo s_signbit.lo s_trunc.lo + s_cbrt.lo s_exp10.lo s_expm1.lo s_ilogb.lo s_infinity.lo \ + s_isinf.lo s_isinfd.lo s_isnan.lo s_isnand.lo s_log1p.lo \ + s_nan.lo s_nextafter.lo s_pow10.lo s_rint.lo s_logb.lo \ + s_log2.lo s_matherr.lo s_lib_ver.lo s_fdim.lo s_fma.lo \ + s_fmax.lo s_fmin.lo s_fpclassify.lo s_lrint.lo s_llrint.lo \ + s_lround.lo s_llround.lo s_nearbyint.lo s_remquo.lo s_round.lo \ + s_scalbln.lo s_signbit.lo s_trunc.lo am__objects_6 = sf_finite.lo sf_copysign.lo sf_modf.lo sf_scalbn.lo \ sf_cbrt.lo sf_exp10.lo sf_expm1.lo sf_ilogb.lo sf_infinity.lo \ sf_isinf.lo sf_isinff.lo sf_isnan.lo sf_isnanf.lo sf_log1p.lo \ sf_nan.lo sf_nextafter.lo sf_pow10.lo sf_rint.lo sf_logb.lo \ - sf_log2.lo sf_fdim.lo sf_fma.lo sf_fmax.lo sf_fmin.lo \ - sf_fpclassify.lo sf_lrint.lo sf_llrint.lo sf_lround.lo \ - sf_llround.lo sf_nearbyint.lo sf_remquo.lo sf_round.lo \ - sf_scalbln.lo sf_trunc.lo + sf_fdim.lo sf_fma.lo sf_fmax.lo sf_fmin.lo sf_fpclassify.lo \ + sf_lrint.lo sf_llrint.lo sf_lround.lo sf_llround.lo \ + sf_nearbyint.lo sf_remquo.lo sf_round.lo sf_scalbln.lo \ + sf_trunc.lo sf_exp.lo sf_exp2.lo sf_exp2_data.lo sf_log.lo \ + sf_log_data.lo sf_log2.lo sf_log2_data.lo sf_pow_log2_data.lo \ + sf_pow.lo math_errf.lo am__objects_7 = atanl.lo cosl.lo sinl.lo tanl.lo tanhl.lo frexpl.lo \ modfl.lo ceill.lo fabsl.lo floorl.lo log1pl.lo expm1l.lo \ acosl.lo asinl.lo atan2l.lo coshl.lo sinhl.lo expl.lo \ @@ -347,11 +354,14 @@ fsrc = sf_finite.c sf_copysign.c sf_modf.c sf_scalbn.c \ sf_cbrt.c sf_exp10.c sf_expm1.c sf_ilogb.c \ sf_infinity.c sf_isinf.c sf_isinff.c sf_isnan.c sf_isnanf.c \ sf_log1p.c sf_nan.c sf_nextafter.c sf_pow10.c \ - sf_rint.c sf_logb.c sf_log2.c \ + sf_rint.c sf_logb.c \ sf_fdim.c sf_fma.c sf_fmax.c sf_fmin.c sf_fpclassify.c \ sf_lrint.c sf_llrint.c \ sf_lround.c sf_llround.c sf_nearbyint.c sf_remquo.c sf_round.c \ - sf_scalbln.c sf_trunc.c + sf_scalbln.c sf_trunc.c \ + sf_exp.c sf_exp2.c sf_exp2_data.c sf_log.c sf_log_data.c \ + sf_log2.c sf_log2_data.c sf_pow_log2_data.c sf_pow.c \ + math_errf.c lsrc = atanl.c cosl.c sinl.c tanl.c tanhl.c frexpl.c modfl.c ceill.c fabsl.c \ floorl.c log1pl.c expm1l.c acosl.c asinl.c atan2l.c coshl.c sinhl.c \ @@ -796,12 +806,6 @@ lib_a-sf_logb.o: sf_logb.c lib_a-sf_logb.obj: sf_logb.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_logb.obj `if test -f 'sf_logb.c'; then $(CYGPATH_W) 'sf_logb.c'; else $(CYGPATH_W) '$(srcdir)/sf_logb.c'; fi` -lib_a-sf_log2.o: sf_log2.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log2.o `test -f 'sf_log2.c' || echo '$(srcdir)/'`sf_log2.c - -lib_a-sf_log2.obj: sf_log2.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log2.obj `if test -f 'sf_log2.c'; then $(CYGPATH_W) 'sf_log2.c'; else $(CYGPATH_W) '$(srcdir)/sf_log2.c'; fi` - lib_a-sf_fdim.o: sf_fdim.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_fdim.o `test -f 'sf_fdim.c' || echo '$(srcdir)/'`sf_fdim.c @@ -886,6 +890,66 @@ lib_a-sf_trunc.o: sf_trunc.c lib_a-sf_trunc.obj: sf_trunc.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_trunc.obj `if test -f 'sf_trunc.c'; then $(CYGPATH_W) 'sf_trunc.c'; else $(CYGPATH_W) '$(srcdir)/sf_trunc.c'; fi` +lib_a-sf_exp.o: sf_exp.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_exp.o `test -f 'sf_exp.c' || echo '$(srcdir)/'`sf_exp.c + +lib_a-sf_exp.obj: sf_exp.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_exp.obj `if test -f 'sf_exp.c'; then $(CYGPATH_W) 'sf_exp.c'; else $(CYGPATH_W) '$(srcdir)/sf_exp.c'; fi` + +lib_a-sf_exp2.o: sf_exp2.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_exp2.o `test -f 'sf_exp2.c' || echo '$(srcdir)/'`sf_exp2.c + +lib_a-sf_exp2.obj: sf_exp2.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_exp2.obj `if test -f 'sf_exp2.c'; then $(CYGPATH_W) 'sf_exp2.c'; else $(CYGPATH_W) '$(srcdir)/sf_exp2.c'; fi` + +lib_a-sf_exp2_data.o: sf_exp2_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_exp2_data.o `test -f 'sf_exp2_data.c' || echo '$(srcdir)/'`sf_exp2_data.c + +lib_a-sf_exp2_data.obj: sf_exp2_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_exp2_data.obj `if test -f 'sf_exp2_data.c'; then $(CYGPATH_W) 'sf_exp2_data.c'; else $(CYGPATH_W) '$(srcdir)/sf_exp2_data.c'; fi` + +lib_a-sf_log.o: sf_log.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log.o `test -f 'sf_log.c' || echo '$(srcdir)/'`sf_log.c + +lib_a-sf_log.obj: sf_log.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log.obj `if test -f 'sf_log.c'; then $(CYGPATH_W) 'sf_log.c'; else $(CYGPATH_W) '$(srcdir)/sf_log.c'; fi` + +lib_a-sf_log_data.o: sf_log_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log_data.o `test -f 'sf_log_data.c' || echo '$(srcdir)/'`sf_log_data.c + +lib_a-sf_log_data.obj: sf_log_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log_data.obj `if test -f 'sf_log_data.c'; then $(CYGPATH_W) 'sf_log_data.c'; else $(CYGPATH_W) '$(srcdir)/sf_log_data.c'; fi` + +lib_a-sf_log2.o: sf_log2.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log2.o `test -f 'sf_log2.c' || echo '$(srcdir)/'`sf_log2.c + +lib_a-sf_log2.obj: sf_log2.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log2.obj `if test -f 'sf_log2.c'; then $(CYGPATH_W) 'sf_log2.c'; else $(CYGPATH_W) '$(srcdir)/sf_log2.c'; fi` + +lib_a-sf_log2_data.o: sf_log2_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log2_data.o `test -f 'sf_log2_data.c' || echo '$(srcdir)/'`sf_log2_data.c + +lib_a-sf_log2_data.obj: sf_log2_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_log2_data.obj `if test -f 'sf_log2_data.c'; then $(CYGPATH_W) 'sf_log2_data.c'; else $(CYGPATH_W) '$(srcdir)/sf_log2_data.c'; fi` + +lib_a-sf_pow_log2_data.o: sf_pow_log2_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_pow_log2_data.o `test -f 'sf_pow_log2_data.c' || echo '$(srcdir)/'`sf_pow_log2_data.c + +lib_a-sf_pow_log2_data.obj: sf_pow_log2_data.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_pow_log2_data.obj `if test -f 'sf_pow_log2_data.c'; then $(CYGPATH_W) 'sf_pow_log2_data.c'; else $(CYGPATH_W) '$(srcdir)/sf_pow_log2_data.c'; fi` + +lib_a-sf_pow.o: sf_pow.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_pow.o `test -f 'sf_pow.c' || echo '$(srcdir)/'`sf_pow.c + +lib_a-sf_pow.obj: sf_pow.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-sf_pow.obj `if test -f 'sf_pow.c'; then $(CYGPATH_W) 'sf_pow.c'; else $(CYGPATH_W) '$(srcdir)/sf_pow.c'; fi` + +lib_a-math_errf.o: math_errf.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-math_errf.o `test -f 'math_errf.c' || echo '$(srcdir)/'`math_errf.c + +lib_a-math_errf.obj: math_errf.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-math_errf.obj `if test -f 'math_errf.c'; then $(CYGPATH_W) 'math_errf.c'; else $(CYGPATH_W) '$(srcdir)/math_errf.c'; fi` + lib_a-atanl.o: atanl.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-atanl.o `test -f 'atanl.c' || echo '$(srcdir)/'`atanl.c diff --git a/newlib/libm/common/math_config.h b/newlib/libm/common/math_config.h new file mode 100644 index 000000000..c5667844a --- /dev/null +++ b/newlib/libm/common/math_config.h @@ -0,0 +1,179 @@ +/* Configuration for math routines. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef _MATH_CONFIG_H +#define _MATH_CONFIG_H + +#include +#include + +#ifndef WANT_ROUNDING +/* Correct special case results in non-nearest rounding modes. */ +# define WANT_ROUNDING 1 +#endif +#ifndef WANT_ERRNO +/* Set errno according to ISO C with (math_errhandling & MATH_ERRNO) != 0. */ +# define WANT_ERRNO 1 +#endif +#ifndef WANT_ERRNO_UFLOW +/* Set errno to ERANGE if result underflows to 0 (in all rounding modes). */ +# define WANT_ERRNO_UFLOW (WANT_ROUNDING && WANT_ERRNO) +#endif + +#ifndef TOINT_INTRINSICS +# define TOINT_INTRINSICS 0 +#endif +#ifndef TOINT_RINT +# define TOINT_RINT 0 +#endif +#ifndef TOINT_SHIFT +# define TOINT_SHIFT 1 +#endif + +static inline uint32_t +asuint (float f) +{ + union + { + float f; + uint32_t i; + } u = {f}; + return u.i; +} + +static inline float +asfloat (uint32_t i) +{ + union + { + uint32_t i; + float f; + } u = {i}; + return u.f; +} + +static inline uint64_t +asuint64 (double f) +{ + union + { + double f; + uint64_t i; + } u = {f}; + return u.i; +} + +static inline double +asdouble (uint64_t i) +{ + union + { + uint64_t i; + double f; + } u = {i}; + return u.f; +} + +#ifndef IEEE_754_2008_SNAN +# define IEEE_754_2008_SNAN 1 +#endif +static inline int +issignalingf_inline (float x) +{ + uint32_t ix = asuint (x); + if (!IEEE_754_2008_SNAN) + return (ix & 0x7fc00000) == 0x7fc00000; + return 2 * (ix ^ 0x00400000) > 2u * 0x7fc00000; +} + +#ifdef __GNUC__ +# define HIDDEN __attribute__ ((__visibility__ ("hidden"))) +# define NOINLINE __attribute__ ((noinline)) +#else +# define HIDDEN +# define NOINLINE +#endif + +HIDDEN float __math_oflowf (unsigned long); +HIDDEN float __math_uflowf (unsigned long); +HIDDEN float __math_may_uflowf (unsigned long); +HIDDEN float __math_divzerof (unsigned long); +HIDDEN float __math_invalidf (float); + +/* Shared between expf, exp2f and powf. */ +#define EXP2F_TABLE_BITS 5 +#define EXP2F_POLY_ORDER 3 +extern const struct exp2f_data +{ + uint64_t tab[1 << EXP2F_TABLE_BITS]; + double shift_scaled; + double poly[EXP2F_POLY_ORDER]; + double shift; + double invln2_scaled; + double poly_scaled[EXP2F_POLY_ORDER]; +} __exp2f_data HIDDEN; + +#define LOGF_TABLE_BITS 4 +#define LOGF_POLY_ORDER 4 +extern const struct logf_data +{ + struct + { + double invc, logc; + } tab[1 << LOGF_TABLE_BITS]; + double ln2; + double poly[LOGF_POLY_ORDER - 1]; /* First order coefficient is 1. */ +} __logf_data HIDDEN; + +#define LOG2F_TABLE_BITS 4 +#define LOG2F_POLY_ORDER 4 +extern const struct log2f_data +{ + struct + { + double invc, logc; + } tab[1 << LOG2F_TABLE_BITS]; + double poly[LOG2F_POLY_ORDER]; +} __log2f_data HIDDEN; + +#define POWF_LOG2_TABLE_BITS 4 +#define POWF_LOG2_POLY_ORDER 5 +#if TOINT_INTRINSICS +# define POWF_SCALE_BITS EXP2F_TABLE_BITS +#else +# define POWF_SCALE_BITS 0 +#endif +#define POWF_SCALE ((double) (1 << POWF_SCALE_BITS)) +extern const struct powf_log2_data +{ + struct + { + double invc, logc; + } tab[1 << POWF_LOG2_TABLE_BITS]; + double poly[POWF_LOG2_POLY_ORDER]; +} __powf_log2_data HIDDEN; + +#endif diff --git a/newlib/libm/common/math_errf.c b/newlib/libm/common/math_errf.c new file mode 100644 index 000000000..60b1bb3f2 --- /dev/null +++ b/newlib/libm/common/math_errf.c @@ -0,0 +1,89 @@ +/* Single-precision math error handling. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include "math_config.h" + +#if WANT_ERRNO +#include +/* NOINLINE reduces code size and avoids making math functions non-leaf + when the error handling is inlined. */ +NOINLINE static float +with_errnof (float y, int e) +{ + errno = e; + return y; +} +#else +#define with_errnof(x, e) (x) +#endif + +/* NOINLINE prevents fenv semantics breaking optimizations. */ +NOINLINE static float +xflowf (unsigned long sign, float y) +{ + y = (sign ? -y : y) * y; + return with_errnof (y, ERANGE); +} + +HIDDEN float +__math_uflowf (unsigned long sign) +{ + return xflowf (sign, 0x1p-95f); +} + +#if WANT_ERRNO_UFLOW +/* Underflows to zero in some non-nearest rounding mode, setting errno + is valid even if the result is non-zero, but in the subnormal range. */ +HIDDEN float +__math_may_uflowf (unsigned long sign) +{ + return xflowf (sign, 0x1.4p-75f); +} +#endif + +HIDDEN float +__math_oflowf (unsigned long sign) +{ + return xflowf (sign, 0x1p97f); +} + +HIDDEN float +__math_divzerof (unsigned long sign) +{ + float y = 0; + return with_errnof ((sign ? -1 : 1) / y, ERANGE); +} + +HIDDEN float +__math_invalidf (float x) +{ + float y = (x - x) / (x - x); + return isnan (x) ? y : with_errnof (y, EDOM); +} +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_exp.c b/newlib/libm/common/sf_exp.c new file mode 100644 index 000000000..79ec62bf5 --- /dev/null +++ b/newlib/libm/common/sf_exp.c @@ -0,0 +1,113 @@ +/* Single-precision e^x function. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include +#include +#include "math_config.h" + +/* +EXP2F_TABLE_BITS = 5 +EXP2F_POLY_ORDER = 3 + +ULP error: 0.502 (nearest rounding.) +Relative error: 1.69 * 2^-34 in [-ln2/64, ln2/64] (before rounding.) +Wrong count: 170635 (all nearest rounding wrong results with fma.) +Non-nearest ULP error: 1 (rounded ULP error) +*/ + +#define N (1 << EXP2F_TABLE_BITS) +#define InvLn2N __exp2f_data.invln2_scaled +#define T __exp2f_data.tab +#define C __exp2f_data.poly_scaled + +static inline uint32_t +top12 (float x) +{ + return asuint (x) >> 20; +} + +float +expf (float x) +{ + uint32_t abstop; + uint64_t ki, t; + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t kd, xd, z, r, r2, y, s; + + xd = (double_t) x; + abstop = top12 (x) & 0x7ff; + if (__builtin_expect (abstop >= top12 (88.0f), 0)) + { + /* |x| >= 88 or x is nan. */ + if (asuint (x) == asuint (-INFINITY)) + return 0.0f; + if (abstop >= top12 (INFINITY)) + return x + x; + if (x > 0x1.62e42ep6f) /* x > log(0x1p128) ~= 88.72 */ + return __math_oflowf (0); + if (x < -0x1.9fe368p6f) /* x < log(0x1p-150) ~= -103.97 */ + return __math_uflowf (0); +#if WANT_ERRNO_UFLOW + if (x < -0x1.9d1d9ep6f) /* x < log(0x1p-149) ~= -103.28 */ + return __math_may_uflowf (0); +#endif + } + + /* x*N/Ln2 = k + r with r in [-1/2, 1/2] and int k. */ + z = InvLn2N * xd; + + /* Round and convert z to int, the result is in [-150*N, 128*N] and + ideally ties-to-even rule is used, otherwise the magnitude of r + can be bigger which gives larger approximation error. */ +#if TOINT_INTRINSICS + kd = roundtoint (z); + ki = converttoint (z); +#elif TOINT_RINT + kd = rint (z); + ki = (long) kd; +#elif TOINT_SHIFT +# define SHIFT __exp2f_data.shift + kd = (double) (z + SHIFT); /* Rounding to double precision is required. */ + ki = asuint64 (kd); + kd -= SHIFT; +#endif + r = z - kd; + + /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ + t = T[ki % N]; + t += ki << (52 - EXP2F_TABLE_BITS); + s = asdouble (t); + z = C[0] * r + C[1]; + r2 = r * r; + y = C[2] * r + 1; + y = z * r2 + y; + y = y * s; + return (float) y; +} +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_exp2.c b/newlib/libm/common/sf_exp2.c new file mode 100644 index 000000000..75f2551c1 --- /dev/null +++ b/newlib/libm/common/sf_exp2.c @@ -0,0 +1,99 @@ +/* Single-precision 2^x function. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include +#include +#include "math_config.h" + +/* +EXP2F_TABLE_BITS = 5 +EXP2F_POLY_ORDER = 3 + +ULP error: 0.502 (nearest rounding.) +Relative error: 1.69 * 2^-34 in [-1/64, 1/64] (before rounding.) +Wrong count: 168353 (all nearest rounding wrong results with fma.) +Non-nearest ULP error: 1 (rounded ULP error) +*/ + +#define N (1 << EXP2F_TABLE_BITS) +#define T __exp2f_data.tab +#define C __exp2f_data.poly +#define SHIFT __exp2f_data.shift_scaled + +static inline uint32_t +top12 (float x) +{ + return asuint (x) >> 20; +} + +float +exp2f (float x) +{ + uint32_t abstop; + uint64_t ki, t; + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t kd, xd, z, r, r2, y, s; + + xd = (double_t) x; + abstop = top12 (x) & 0x7ff; + if (__builtin_expect (abstop >= top12 (128.0f), 0)) + { + /* |x| >= 128 or x is nan. */ + if (asuint (x) == asuint (-INFINITY)) + return 0.0f; + if (abstop >= top12 (INFINITY)) + return x + x; + if (x > 0.0f) + return __math_oflowf (0); + if (x <= -150.0f) + return __math_uflowf (0); +#if WANT_ERRNO_UFLOW + if (x < -149.0f) + return __math_may_uflowf (0); +#endif + } + + /* x = k/N + r with r in [-1/(2N), 1/(2N)] and int k. */ + kd = (double) (xd + SHIFT); /* Rounding to double precision is required. */ + ki = asuint64 (kd); + kd -= SHIFT; /* k/N for int k. */ + r = xd - kd; + + /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ + t = T[ki % N]; + t += ki << (52 - EXP2F_TABLE_BITS); + s = asdouble (t); + z = C[0] * r + C[1]; + r2 = r * r; + y = C[2] * r + 1; + y = z * r2 + y; + y = y * s; + return (float) y; +} +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_exp2_data.c b/newlib/libm/common/sf_exp2_data.c new file mode 100644 index 000000000..63b6f391d --- /dev/null +++ b/newlib/libm/common/sf_exp2_data.c @@ -0,0 +1,56 @@ +/* Shared data between expf, exp2f and powf. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include "math_config.h" + +#define N (1 << EXP2F_TABLE_BITS) + +const struct exp2f_data __exp2f_data = { + /* tab[i] = uint(2^(i/N)) - (i << 52-BITS) + used for computing 2^(k/N) for an int |k| < 150 N as + double(tab[k%N] + (k << 52-BITS)) */ + .tab = { +0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, +0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1, +0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d, +0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585, +0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13, +0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d, +0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069, +0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540, + }, + .shift_scaled = 0x1.8p+52 / N, + .poly = { 0x1.c6af84b912394p-5, 0x1.ebfce50fac4f3p-3, 0x1.62e42ff0c52d6p-1 }, + .shift = 0x1.8p+52, + .invln2_scaled = 0x1.71547652b82fep+0 * N, + .poly_scaled = { +0x1.c6af84b912394p-5/N/N/N, 0x1.ebfce50fac4f3p-3/N/N, 0x1.62e42ff0c52d6p-1/N + }, +}; +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_log.c b/newlib/libm/common/sf_log.c new file mode 100644 index 000000000..ba5558a54 --- /dev/null +++ b/newlib/libm/common/sf_log.c @@ -0,0 +1,98 @@ +/* Single-precision log function. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include +#include +#include "math_config.h" + +/* +LOGF_TABLE_BITS = 4 +LOGF_POLY_ORDER = 4 + +ULP error: 0.818 (nearest rounding.) +Relative error: 1.957 * 2^-26 (before rounding.) +*/ + +#define T __logf_data.tab +#define A __logf_data.poly +#define Ln2 __logf_data.ln2 +#define N (1 << LOGF_TABLE_BITS) +#define OFF 0x3f330000 + +float +logf (float x) +{ + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t z, r, r2, y, y0, invc, logc; + uint32_t ix, iz, tmp; + int k, i; + + ix = asuint (x); +#if WANT_ROUNDING + /* Fix sign of zero with downward rounding when x==1. */ + if (__builtin_expect (ix == 0x3f800000, 0)) + return 0; +#endif + if (__builtin_expect (ix - 0x00800000 >= 0x7f800000 - 0x00800000, 0)) + { + /* x < 0x1p-126 or inf or nan. */ + if (ix * 2 == 0) + return __math_divzerof (1); + if (ix == 0x7f800000) /* log(inf) == inf. */ + return x; + if ((ix & 0x80000000) || ix * 2 >= 0xff000000) + return __math_invalidf (x); + /* x is subnormal, normalize it. */ + ix = asuint (x * 0x1p23f); + ix -= 23 << 23; + } + + /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. + The range is split into N subintervals. + The ith subinterval contains z and c is near its center. */ + tmp = ix - OFF; + i = (tmp >> (23 - LOGF_TABLE_BITS)) % N; + k = (int32_t) tmp >> 23; /* arithmetic shift */ + iz = ix - (tmp & 0x1ff << 23); + invc = T[i].invc; + logc = T[i].logc; + z = (double_t) asfloat (iz); + + /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */ + r = z * invc - 1; + y0 = logc + (double_t) k * Ln2; + + /* Pipelined polynomial evaluation to approximate log1p(r). */ + r2 = r * r; + y = A[1] * r + A[2]; + y = A[0] * r2 + y; + y = y * r2 + (y0 + r); + return (float) y; +} +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_log2.c b/newlib/libm/common/sf_log2.c index 9fbaaca72..f52cd385d 100644 --- a/newlib/libm/common/sf_log2.c +++ b/newlib/libm/common/sf_log2.c @@ -1,48 +1,99 @@ -/* sf_log2.c -- float version of s_log2.c. - * Modification of sf_exp10.c by Yaakov Selkowitz 2009. - */ +/* Single-precision log2 function. + Copyright (c) 2017 ARM Ltd. All rights reserved. -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. -/* - * wrapper log2f(x) - */ + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "fdlibm.h" -#include +#if !__OBSOLETE_MATH + #include -#undef log2 -#undef log2f +#include +#include "math_config.h" -#ifdef __STDC__ - float log2f(float x) /* wrapper log2f */ -#else - float log2f(x) /* wrapper log2f */ - float x; -#endif +/* +LOG2F_TABLE_BITS = 4 +LOG2F_POLY_ORDER = 4 + +ULP error: 0.752 (nearest rounding.) +Relative error: 1.9 * 2^-26 (before rounding.) +*/ + +#define N (1 << LOG2F_TABLE_BITS) +#define T __log2f_data.tab +#define A __log2f_data.poly +#define OFF 0x3f330000 + +float +log2f (float x) { - return (logf(x) / (float_t) M_LN2); -} + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t z, r, r2, p, y, y0, invc, logc; + uint32_t ix, iz, top, tmp; + int k, i; -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double log2(double x) -#else - double log2(x) - double x; + ix = asuint (x); +#if WANT_ROUNDING + /* Fix sign of zero with downward rounding when x==1. */ + if (__builtin_expect (ix == 0x3f800000, 0)) + return 0; #endif -{ - return (double) log2f((float) x); -} + if (__builtin_expect (ix - 0x00800000 >= 0x7f800000 - 0x00800000, 0)) + { + /* x < 0x1p-126 or inf or nan. */ + if (ix * 2 == 0) + return __math_divzerof (1); + if (ix == 0x7f800000) /* log2(inf) == inf. */ + return x; + if ((ix & 0x80000000) || ix * 2 >= 0xff000000) + return __math_invalidf (x); + /* x is subnormal, normalize it. */ + ix = asuint (x * 0x1p23f); + ix -= 23 << 23; + } -#endif /* defined(_DOUBLE_IS_32BITS) */ + /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. + The range is split into N subintervals. + The ith subinterval contains z and c is near its center. */ + tmp = ix - OFF; + i = (tmp >> (23 - LOG2F_TABLE_BITS)) % N; + top = tmp & 0xff800000; + iz = ix - top; + k = (int32_t) tmp >> 23; /* arithmetic shift */ + invc = T[i].invc; + logc = T[i].logc; + z = (double_t) asfloat (iz); + + /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */ + r = z * invc - 1; + y0 = logc + (double_t) k; + + /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */ + r2 = r * r; + y = A[1] * r + A[2]; + y = A[0] * r2 + y; + p = A[3] * r + y0; + y = y * r2 + p; + return (float) y; +} +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_log2_data.c b/newlib/libm/common/sf_log2_data.c new file mode 100644 index 000000000..f0e80947c --- /dev/null +++ b/newlib/libm/common/sf_log2_data.c @@ -0,0 +1,56 @@ +/* Data definition for log2f. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include "math_config.h" + +const struct log2f_data __log2f_data = { + .tab = { + { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 }, + { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 }, + { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 }, + { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 }, + { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 }, + { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 }, + { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 }, + { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 }, + { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 }, + { 0x1p+0, 0x0p+0 }, + { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 }, + { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 }, + { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 }, + { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 }, + { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 }, + { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 }, + }, + .poly = { + -0x1.712b6f70a7e4dp-2, 0x1.ecabf496832ep-2, -0x1.715479ffae3dep-1, + 0x1.715475f35c8b8p0, + } +}; +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_log_data.c b/newlib/libm/common/sf_log_data.c new file mode 100644 index 000000000..28231b4dc --- /dev/null +++ b/newlib/libm/common/sf_log_data.c @@ -0,0 +1,56 @@ +/* Data definition for logf. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include "math_config.h" + +const struct logf_data __logf_data = { + .tab = { + { 0x1.661ec79f8f3bep+0, -0x1.57bf7808caadep-2 }, + { 0x1.571ed4aaf883dp+0, -0x1.2bef0a7c06ddbp-2 }, + { 0x1.49539f0f010bp+0, -0x1.01eae7f513a67p-2 }, + { 0x1.3c995b0b80385p+0, -0x1.b31d8a68224e9p-3 }, + { 0x1.30d190c8864a5p+0, -0x1.6574f0ac07758p-3 }, + { 0x1.25e227b0b8eap+0, -0x1.1aa2bc79c81p-3 }, + { 0x1.1bb4a4a1a343fp+0, -0x1.a4e76ce8c0e5ep-4 }, + { 0x1.12358f08ae5bap+0, -0x1.1973c5a611cccp-4 }, + { 0x1.0953f419900a7p+0, -0x1.252f438e10c1ep-5 }, + { 0x1p+0, 0x0p+0 }, + { 0x1.e608cfd9a47acp-1, 0x1.aa5aa5df25984p-5 }, + { 0x1.ca4b31f026aap-1, 0x1.c5e53aa362eb4p-4 }, + { 0x1.b2036576afce6p-1, 0x1.526e57720db08p-3 }, + { 0x1.9c2d163a1aa2dp-1, 0x1.bc2860d22477p-3 }, + { 0x1.886e6037841edp-1, 0x1.1058bc8a07ee1p-2 }, + { 0x1.767dcf5534862p-1, 0x1.4043057b6ee09p-2 }, + }, + .ln2 = 0x1.62e42fefa39efp-1, + .poly = { + -0x1.00ea348b88334p-2, 0x1.5575b0be00b6ap-2, -0x1.ffffef20a4123p-2, + } +}; +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_pow.c b/newlib/libm/common/sf_pow.c new file mode 100644 index 000000000..6741a349b --- /dev/null +++ b/newlib/libm/common/sf_pow.c @@ -0,0 +1,230 @@ +/* Single-precision pow function. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include +#include +#include "math_config.h" + +/* +POWF_LOG2_POLY_ORDER = 5 +EXP2F_TABLE_BITS = 5 + +ULP error: 0.82 (~ 0.5 + relerr*2^24) +relerr: 1.27 * 2^-26 (Relative error ~= 128*Ln2*relerr_log2 + relerr_exp2) +relerr_log2: 1.83 * 2^-33 (Relative error of logx.) +relerr_exp2: 1.69 * 2^-34 (Relative error of exp2(ylogx).) +*/ + +#define N (1 << POWF_LOG2_TABLE_BITS) +#define T __powf_log2_data.tab +#define A __powf_log2_data.poly +#define OFF 0x3f330000 + +/* Subnormal input is normalized so ix has negative biased exponent. + Output is multiplied by N (POWF_SCALE) if TOINT_INTRINICS is set. */ +static inline double_t +log2_inline (uint32_t ix) +{ + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t z, r, r2, r4, p, q, y, y0, invc, logc; + uint32_t iz, top, tmp; + int k, i; + + /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. + The range is split into N subintervals. + The ith subinterval contains z and c is near its center. */ + tmp = ix - OFF; + i = (tmp >> (23 - POWF_LOG2_TABLE_BITS)) % N; + top = tmp & 0xff800000; + iz = ix - top; + k = (int32_t) top >> (23 - POWF_SCALE_BITS); /* arithmetic shift */ + invc = T[i].invc; + logc = T[i].logc; + z = (double_t) asfloat (iz); + + /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */ + r = z * invc - 1; + y0 = logc + (double_t) k; + + /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */ + r2 = r * r; + y = A[0] * r + A[1]; + p = A[2] * r + A[3]; + r4 = r2 * r2; + q = A[4] * r + y0; + q = p * r2 + q; + y = y * r4 + q; + return y; +} + +#undef N +#undef T +#define N (1 << EXP2F_TABLE_BITS) +#define T __exp2f_data.tab +#define SIGN_BIAS (1 << (EXP2F_TABLE_BITS + 11)) + +/* The output of log2 and thus the input of exp2 is either scaled by N + (in case of fast toint intrinsics) or not. The unscaled xd must be + in [-1021,1023], sign_bias sets the sign of the result. */ +static inline double_t +exp2_inline (double_t xd, unsigned long sign_bias) +{ + uint64_t ki, ski, t; + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t kd, z, r, r2, y, s; + +#if TOINT_INTRINSICS +# define C __exp2f_data.poly_scaled + /* N*x = k + r with r in [-1/2, 1/2] */ + kd = roundtoint (xd); /* k */ + ki = converttoint (xd); +#else +# define C __exp2f_data.poly +# define SHIFT __exp2f_data.shift_scaled + /* x = k/N + r with r in [-1/(2N), 1/(2N)] */ + kd = (double) (xd + SHIFT); /* Rounding to double precision is required. */ + ki = asuint64 (kd); + kd -= SHIFT; /* k/N */ +#endif + r = xd - kd; + + /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ + t = T[ki % N]; + ski = ki + sign_bias; + t += ski << (52 - EXP2F_TABLE_BITS); + s = asdouble (t); + z = C[0] * r + C[1]; + r2 = r * r; + y = C[2] * r + 1; + y = z * r2 + y; + y = y * s; + return y; +} + +/* Returns 0 if not int, 1 if odd int, 2 if even int. */ +static inline int +checkint (uint32_t iy) +{ + int e = iy >> 23 & 0xff; + if (e < 0x7f) + return 0; + if (e > 0x7f + 23) + return 2; + if (iy & ((1 << (0x7f + 23 - e)) - 1)) + return 0; + if (iy & (1 << (0x7f + 23 - e))) + return 1; + return 2; +} + +static inline int +zeroinfnan (uint32_t ix) +{ + return 2 * ix - 1 >= 2u * 0x7f800000 - 1; +} + +float +powf (float x, float y) +{ + unsigned long sign_bias = 0; + uint32_t ix, iy; + + ix = asuint (x); + iy = asuint (y); + if (__builtin_expect (ix - 0x00800000 >= 0x7f800000 - 0x00800000 + || zeroinfnan (iy), + 0)) + { + /* Either (x < 0x1p-126 or inf or nan) or (y is 0 or inf or nan). */ + if (__builtin_expect (zeroinfnan (iy), 0)) + { + if (2 * iy == 0) + return issignalingf_inline (x) ? x + y : 1.0f; + if (ix == 0x3f800000) + return issignalingf_inline (y) ? x + y : 1.0f; + if (2 * ix > 2u * 0x7f800000 || 2 * iy > 2u * 0x7f800000) + return x + y; + if (2 * ix == 2 * 0x3f800000) + return 1.0f; + if ((2 * ix < 2 * 0x3f800000) == !(iy & 0x80000000)) + return 0.0f; /* |x|<1 && y==inf or |x|>1 && y==-inf. */ + return y * y; + } + if (__builtin_expect (zeroinfnan (ix), 0)) + { + float_t x2 = x * x; + if (ix & 0x80000000 && checkint (iy) == 1) + { + x2 = -x2; + sign_bias = 1; + } +#if WANT_ERRNO + if (2 * ix == 0 && iy & 0x80000000) + return __math_divzerof (sign_bias); +#endif + return iy & 0x80000000 ? 1 / x2 : x2; + } + /* x and y are non-zero finite. */ + if (ix & 0x80000000) + { + /* Finite x < 0. */ + int yint = checkint (iy); + if (yint == 0) + return __math_invalidf (x); + if (yint == 1) + sign_bias = SIGN_BIAS; + ix &= 0x7fffffff; + } + if (ix < 0x00800000) + { + /* Normalize subnormal x so exponent becomes negative. */ + ix = asuint (x * 0x1p23f); + ix &= 0x7fffffff; + ix -= 23 << 23; + } + } + double_t logx = log2_inline (ix); + double_t ylogx = y * logx; /* Note: cannot overflow, y is single prec. */ + if (__builtin_expect ((asuint64 (ylogx) >> 47 & 0xffff) + >= asuint64 (126.0 * POWF_SCALE) >> 47, + 0)) + { + /* |y*log(x)| >= 126. */ + if (ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE) + return __math_oflowf (sign_bias); + if (ylogx <= -150.0 * POWF_SCALE) + return __math_uflowf (sign_bias); +#if WANT_ERRNO_UFLOW + if (ylogx < -149.0 * POWF_SCALE) + return __math_may_uflowf (sign_bias); +#endif + } + return (float) exp2_inline (ylogx, sign_bias); +} +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/common/sf_pow_log2_data.c b/newlib/libm/common/sf_pow_log2_data.c new file mode 100644 index 000000000..24f638c19 --- /dev/null +++ b/newlib/libm/common/sf_pow_log2_data.c @@ -0,0 +1,57 @@ +/* Data definition for powf. + Copyright (c) 2017 ARM Ltd. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "fdlibm.h" +#if !__OBSOLETE_MATH + +#include "math_config.h" + +const struct powf_log2_data __powf_log2_data = { + .tab = { + { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 * POWF_SCALE }, + { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 * POWF_SCALE }, + { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 * POWF_SCALE }, + { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 * POWF_SCALE }, + { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 * POWF_SCALE }, + { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 * POWF_SCALE }, + { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 * POWF_SCALE }, + { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 * POWF_SCALE }, + { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 * POWF_SCALE }, + { 0x1p+0, 0x0p+0 * POWF_SCALE }, + { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 * POWF_SCALE }, + { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 * POWF_SCALE }, + { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 * POWF_SCALE }, + { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 * POWF_SCALE }, + { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 * POWF_SCALE }, + { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 * POWF_SCALE }, + }, + .poly = { + 0x1.27616c9496e0bp-2 * POWF_SCALE, -0x1.71969a075c67ap-2 * POWF_SCALE, + 0x1.ec70a6ca7baddp-2 * POWF_SCALE, -0x1.7154748bef6c8p-1 * POWF_SCALE, + 0x1.71547652ab82bp0 * POWF_SCALE, + } +}; +#endif /* !__OBSOLETE_MATH */ diff --git a/newlib/libm/math/Makefile.am b/newlib/libm/math/Makefile.am index 9e8e92840..e745159ae 100644 --- a/newlib/libm/math/Makefile.am +++ b/newlib/libm/math/Makefile.am @@ -48,7 +48,8 @@ fsrc = kf_rem_pio2.c \ sf_frexp.c sf_ldexp.c \ sf_signif.c sf_sin.c \ sf_tan.c sf_tanh.c \ - wf_exp2.c wf_tgamma.c + wf_exp2.c wf_tgamma.c \ + wf_log2.c lsrc = el_hypot.c diff --git a/newlib/libm/math/Makefile.in b/newlib/libm/math/Makefile.in index 8f76aad4e..1f5a69406 100644 --- a/newlib/libm/math/Makefile.in +++ b/newlib/libm/math/Makefile.in @@ -137,7 +137,8 @@ am__objects_2 = lib_a-kf_rem_pio2.$(OBJEXT) lib_a-kf_cos.$(OBJEXT) \ lib_a-sf_frexp.$(OBJEXT) lib_a-sf_ldexp.$(OBJEXT) \ lib_a-sf_signif.$(OBJEXT) lib_a-sf_sin.$(OBJEXT) \ lib_a-sf_tan.$(OBJEXT) lib_a-sf_tanh.$(OBJEXT) \ - lib_a-wf_exp2.$(OBJEXT) lib_a-wf_tgamma.$(OBJEXT) + lib_a-wf_exp2.$(OBJEXT) lib_a-wf_tgamma.$(OBJEXT) \ + lib_a-wf_log2.$(OBJEXT) am__objects_3 = lib_a-el_hypot.$(OBJEXT) @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \ @USE_LIBTOOL_FALSE@ $(am__objects_2) $(am__objects_3) @@ -169,7 +170,7 @@ am__objects_5 = kf_rem_pio2.lo kf_cos.lo kf_sin.lo kf_tan.lo \ wf_sincos.lo wf_drem.lo sf_asinh.lo sf_atan.lo sf_ceil.lo \ sf_cos.lo sf_erf.lo sf_fabs.lo sf_floor.lo sf_frexp.lo \ sf_ldexp.lo sf_signif.lo sf_sin.lo sf_tan.lo sf_tanh.lo \ - wf_exp2.lo wf_tgamma.lo + wf_exp2.lo wf_tgamma.lo wf_log2.lo am__objects_6 = el_hypot.lo @USE_LIBTOOL_TRUE@am_libmath_la_OBJECTS = $(am__objects_4) \ @USE_LIBTOOL_TRUE@ $(am__objects_5) $(am__objects_6) @@ -372,7 +373,8 @@ fsrc = kf_rem_pio2.c \ sf_frexp.c sf_ldexp.c \ sf_signif.c sf_sin.c \ sf_tan.c sf_tanh.c \ - wf_exp2.c wf_tgamma.c + wf_exp2.c wf_tgamma.c \ + wf_log2.c lsrc = el_hypot.c libmath_la_LDFLAGS = -Xcompiler -nostdlib @@ -1270,6 +1272,12 @@ lib_a-wf_tgamma.o: wf_tgamma.c lib_a-wf_tgamma.obj: wf_tgamma.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wf_tgamma.obj `if test -f 'wf_tgamma.c'; then $(CYGPATH_W) 'wf_tgamma.c'; else $(CYGPATH_W) '$(srcdir)/wf_tgamma.c'; fi` +lib_a-wf_log2.o: wf_log2.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wf_log2.o `test -f 'wf_log2.c' || echo '$(srcdir)/'`wf_log2.c + +lib_a-wf_log2.obj: wf_log2.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wf_log2.obj `if test -f 'wf_log2.c'; then $(CYGPATH_W) 'wf_log2.c'; else $(CYGPATH_W) '$(srcdir)/wf_log2.c'; fi` + lib_a-el_hypot.o: el_hypot.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-el_hypot.o `test -f 'el_hypot.c' || echo '$(srcdir)/'`el_hypot.c diff --git a/newlib/libm/math/ef_exp.c b/newlib/libm/math/ef_exp.c index 6824f991a..e817370ac 100644 --- a/newlib/libm/math/ef_exp.c +++ b/newlib/libm/math/ef_exp.c @@ -15,6 +15,7 @@ #include "fdlibm.h" +#if __OBSOLETE_MATH #ifdef __v810__ #define const #endif @@ -97,3 +98,4 @@ P5 = 4.1381369442e-08; /* 0x3331bb4c */ return y*twom100; } } +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/ef_log.c b/newlib/libm/math/ef_log.c index 619fe9090..8dc902478 100644 --- a/newlib/libm/math/ef_log.c +++ b/newlib/libm/math/ef_log.c @@ -15,6 +15,7 @@ #include "fdlibm.h" +#if __OBSOLETE_MATH #ifdef __STDC__ static const float #else @@ -90,3 +91,4 @@ static float zero = 0.0; return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } } +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/ef_pow.c b/newlib/libm/math/ef_pow.c index b3041dbdc..524e3f9b0 100644 --- a/newlib/libm/math/ef_pow.c +++ b/newlib/libm/math/ef_pow.c @@ -15,6 +15,7 @@ #include "fdlibm.h" +#if __OBSOLETE_MATH #ifdef __v810__ #define const #endif @@ -253,3 +254,4 @@ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ else SET_FLOAT_WORD(z,j); return s*z; } +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/wf_exp.c b/newlib/libm/math/wf_exp.c index 70f4459b4..f16af1d1b 100644 --- a/newlib/libm/math/wf_exp.c +++ b/newlib/libm/math/wf_exp.c @@ -18,6 +18,7 @@ */ #include "fdlibm.h" +#if __OBSOLETE_MATH #include #ifdef __STDC__ @@ -101,3 +102,4 @@ u_threshold= -1.0397208405e+02; /* 0xc2cff1b5 */ } #endif /* defined(_DOUBLE_IS_32BITS) */ +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/wf_exp2.c b/newlib/libm/math/wf_exp2.c index 944031405..5dce9c832 100644 --- a/newlib/libm/math/wf_exp2.c +++ b/newlib/libm/math/wf_exp2.c @@ -18,6 +18,7 @@ */ #include "fdlibm.h" +#if __OBSOLETE_MATH #include #include @@ -44,3 +45,4 @@ } #endif /* defined(_DOUBLE_IS_32BITS) */ +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/wf_log.c b/newlib/libm/math/wf_log.c index 4518b863b..07be8d63c 100644 --- a/newlib/libm/math/wf_log.c +++ b/newlib/libm/math/wf_log.c @@ -18,6 +18,7 @@ */ #include "fdlibm.h" +#if __OBSOLETE_MATH #include #ifdef __STDC__ @@ -84,3 +85,4 @@ } #endif /* defined(_DOUBLE_IS_32BITS) */ +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/wf_log2.c b/newlib/libm/math/wf_log2.c new file mode 100644 index 000000000..e32153747 --- /dev/null +++ b/newlib/libm/math/wf_log2.c @@ -0,0 +1,50 @@ +/* wf_log2.c -- float version of s_log2.c. + * Modification of sf_exp10.c by Yaakov Selkowitz 2009. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * wrapper log2f(x) + */ + +#include "fdlibm.h" +#if __OBSOLETE_MATH +#include +#include +#undef log2 +#undef log2f + +#ifdef __STDC__ + float log2f(float x) /* wrapper log2f */ +#else + float log2f(x) /* wrapper log2f */ + float x; +#endif +{ + return (logf(x) / (float_t) M_LN2); +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double log2(double x) +#else + double log2(x) + double x; +#endif +{ + return (double) log2f((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ +#endif /* __OBSOLETE_MATH */ diff --git a/newlib/libm/math/wf_pow.c b/newlib/libm/math/wf_pow.c index a30f8808e..be453558b 100644 --- a/newlib/libm/math/wf_pow.c +++ b/newlib/libm/math/wf_pow.c @@ -18,6 +18,7 @@ */ #include "fdlibm.h" +#if __OBSOLETE_MATH #include #ifdef __STDC__ @@ -177,3 +178,4 @@ } #endif /* defined(_DOUBLE_IS_32BITS) */ +#endif /* __OBSOLETE_MATH */