[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [patches] [PATCH] Make libm smaller using wrappers
- To: "Joseph S. Myers" <joseph@xxxxxxxxxxxxxxxx>
- Subject: Re: [patches] [PATCH] Make libm smaller using wrappers
- From: Maxim Kuvyrkov <maxim@xxxxxxxxxxxxxxxx>
- Date: Wed, 28 Oct 2009 17:36:32 +0300
Maxim Kuvyrkov wrote:
Joseph S. Myers wrote:
On Mon, 12 Oct 2009, Maxim Kuvyrkov wrote:
Joseph, thank you for reviewing this!
The following patch substitutes several double-precision libm
functions with
single-precision counterparts. This transformation certainly
degrades the
precision of computations, but also reduces the size of the libm
library by
more than 50% on some architectures.
...
It seems a good idea to test all the different long double
configurations. mips-linux-gnu (o32) is one where long double is the
same as double. powerpc-linux-gnuspe is one with IBM long double.
You also have IEEE extended long double (e.g. x86 or x86_64) and IEEE
quad long double (e.g. MIPS64 (n32 or n64)) to cover. Testing should
make sure that the same set of symbols at the same versions is still
exported from libm (before the patch, after the patch with the default
configuration and after the patch with the new option group in use),
as well as that there aren't problems with the fallback float or long
double functions trying to call back to the double versions at any point.
OK, I've already done some of the testing above and everything looks
good so far. I'll follow up once all configurations are covered. BTW,
I noted that atest-* do not fail on at least x86, so I will take another
look why they fail on MIPS and PPC. I also reconsidered adding new
tests as opposed to just fixing the existing ones to handle wrappers,
this is why the attached patch doesn't add ldbl-wrap-test.c. We may
still want to keep the dbl-wrap-test.c though.
There was a delay due to fixing random symbols missing on different
architectures, but now I'm proud to present the [hopefully] final
version of the patch.
The updated patch fixes math/test-[i]{float, double, ldouble} tests to
play well with the new option group. Most of the changes to math/ are
to reduce the precision with which the results are checked.
This patch also changes the way ldbl-*/s_erfcl.c and ldbl-*/s_log1pl.c
files are handled. Due to different flavors of ldbl-* support providing
different sets of compatibility symbols it is easier to insert
#if-#else-#endif constructs into all s_erfcl.c and s_log1pl.c
implementations than to handle all differences in one place in
ldbl-wrap/s_{erfcl, log1pl}.c. Therefore ldbl-wrap/ provides
s_erfcl-wrap.c and s_log1pl-wrap.c which is included as appropriate.
Note: there's no ldbl-96/s_log1pl.c, so no changes are necessary there.
Note: ldbl-64-128/ mostly includes ldbl-128/ implementations, so no
changes are necessary there. However, I didn't build sparc32 or s390
toolchains to verify that.
The patch was tested on ldbl-96 (i686, x86_64), ldbl-128 (mips64),
ldbl-128ibm (powerpc-gnuspe) and ldbl-none (arm-gnuebi, mips). Libm
exports same sets of symbols (a) before the patch, (b) after the patch
with new feature turned off, and (c) after the patch with new feature
turned on.
There are no regressions in the math/ tests on i686, x86_64, powerpc and
arm. I686 and x86_64 have no failures at all.
I ran the full testsuite only on i686 and there were no failures.
Any comments? OK to check in?
--
Maxim Kuvyrkov
CodeSourcery
maxim@xxxxxxxxxxxxxxxx
(650) 331-3385 x724
2009-10-28 Maxim Kuvyrkov <maxim@xxxxxxxxxxxxxxxx>
* option-groups.def (OPTION_EGLIBC_LIBM_BIG): New option group.
* option-groups.defaults (OPTION_EGLIBC_LIBM_BIG): Set.
* configure.in: Handle OPTION_EGLIBC_LIBM_BIG.
* configure: Regenerate.
* math/Makefile (tests: atest-*): Condition on OPTION_EGLIBC_LIBM_BIG.
(libm-test.stmt): Override default result checking precision.
* math/gen-libm-test.pl (default_ulp): New variable. Use it to
override default precision with which test results are checked.
* math/libm-test.inc (MANT_DIG): Handle [l]dbl-wrap math.
* math/test-dbl-wrap: New test.
* sysdeps/ieee754/ldbl-128/s_erfl.c,
* sysdeps/ieee754/ldbl-128/s_log1pl.c,
* sysdeps/ieee754/ldbl-128ibm/s_erfl.c,
* sysdeps/ieee754/ldbl-128ibm/s_log1pl.c,
* sysdeps/ieee754/ldbl-96/s_erfl.c,
* sysdeps/ieee754/ldbl-opt/s_atan.c,
* sysdeps/ieee754/ldbl-opt/s_sin.c,
* sysdeps/ieee754/ldbl-opt/s_tan.c: Handle !OPTION_EGLIBC_LIBM_BIG.
* sysdeps/ieee754/dbl-wrap/dbl-wrap.h,
* sysdeps/ieee754/dbl-wrap/dosincos.c,
* sysdeps/ieee754/dbl-wrap/e_asin.c,
* sysdeps/ieee754/dbl-wrap/e_atan2.c,
* sysdeps/ieee754/dbl-wrap/e_exp.c,
* sysdeps/ieee754/dbl-wrap/e_exp2.c,
* sysdeps/ieee754/dbl-wrap/e_log.c,
* sysdeps/ieee754/dbl-wrap/e_pow.c,
* sysdeps/ieee754/dbl-wrap/s_atan.c,
* sysdeps/ieee754/dbl-wrap/s_sin.c,
* sysdeps/ieee754/dbl-wrap/s_tan.c,
* sysdeps/ieee754/ldbl-wrap/e_acosl.c,
* sysdeps/ieee754/ldbl-wrap/e_asinl.c,
* sysdeps/ieee754/ldbl-wrap/e_expl.c,
* sysdeps/ieee754/ldbl-wrap/e_j0l.c,
* sysdeps/ieee754/ldbl-wrap/e_j1l.c,
* sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c,
* sysdeps/ieee754/ldbl-wrap/e_powl.c,
* sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h,
* sysdeps/ieee754/ldbl-wrap/s_erfl.c,
* sysdeps/ieee754/ldbl-wrap/s_log1pl.c: New files.
configure | 22 ++++++
configure.in | 22 ++++++
math/Makefile | 11 ++-
math/gen-libm-test.pl | 23 ++++--
math/libm-test.inc | 13 ++++
math/test-dbl-wrap.c | 108 +++++++++++++++++++++++++++++
option-groups.def | 13 ++++
option-groups.defaults | 1 +
sysdeps/ieee754/dbl-wrap/dbl-wrap.h | 2 +
sysdeps/ieee754/dbl-wrap/dosincos.c | 1 +
sysdeps/ieee754/dbl-wrap/e_asin.c | 17 +++++
sysdeps/ieee754/dbl-wrap/e_atan2.c | 9 +++
sysdeps/ieee754/dbl-wrap/e_exp.c | 9 +++
sysdeps/ieee754/dbl-wrap/e_exp2.c | 9 +++
sysdeps/ieee754/dbl-wrap/e_log.c | 8 ++
sysdeps/ieee754/dbl-wrap/e_pow.c | 9 +++
sysdeps/ieee754/dbl-wrap/s_atan.c | 13 ++++
sysdeps/ieee754/dbl-wrap/s_sin.c | 27 +++++++
sysdeps/ieee754/dbl-wrap/s_tan.c | 13 ++++
sysdeps/ieee754/ldbl-128/s_erfl.c | 8 ++
sysdeps/ieee754/ldbl-128/s_log1pl.c | 7 ++
sysdeps/ieee754/ldbl-128ibm/s_erfl.c | 8 ++
sysdeps/ieee754/ldbl-128ibm/s_log1pl.c | 7 ++
sysdeps/ieee754/ldbl-96/s_erfl.c | 8 ++
sysdeps/ieee754/ldbl-opt/s_atan.c | 7 ++-
sysdeps/ieee754/ldbl-opt/s_sin.c | 7 ++-
sysdeps/ieee754/ldbl-opt/s_tan.c | 7 ++-
sysdeps/ieee754/ldbl-wrap/e_acosl.c | 9 +++
sysdeps/ieee754/ldbl-wrap/e_asinl.c | 9 +++
sysdeps/ieee754/ldbl-wrap/e_expl.c | 9 +++
sysdeps/ieee754/ldbl-wrap/e_j0l.c | 17 +++++
sysdeps/ieee754/ldbl-wrap/e_j1l.c | 17 +++++
sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c | 9 +++
sysdeps/ieee754/ldbl-wrap/e_powl.c | 10 +++
sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h | 3 +
sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c | 17 +++++
sysdeps/ieee754/ldbl-wrap/s_log1pl-wrap.c | 9 +++
37 files changed, 484 insertions(+), 14 deletions(-)
diff --git a/configure b/configure
index 55bc3e0..afbae1d 100755
--- a/configure
+++ b/configure
@@ -4464,6 +4464,10 @@ if test "$elf" = yes; then
sysnames="`echo $elf_dirs | sed -e 's,//,/,g'` $sysnames"
fi
+# Peek into option-groups.config to check if sysdeps/ieee754/[l]dbl-wrap needs
+# to be included into $sysnames.
+grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config > /dev/null 2>&1
+use_dbl_wrap=$?
# Expand the list of system names into a full list of directories
# from each element's parent name and Implies file (if present).
@@ -4497,6 +4501,14 @@ while test $# -gt 0; do
for x in $implied_candidate; do
found=no
if test -d $xsrcdir$name_base/$x; then
+ # If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
+ # ieee754/dbl-64.
+ if test "$use_dbl_wrap" = "0"; then
+ case $x in
+ ieee754/dbl-64) implied="$implied $name_base/ieee754/dbl-wrap" ;;
+ ieee754/ldbl-*) implied="$implied $name_base/ieee754/ldbl-wrap" ;;
+ esac
+ fi
implied="$implied $name_base/$x";
found=yes
fi
@@ -4510,6 +4522,16 @@ while test $# -gt 0; do
echo "DEBUG: $name implied $x try($d) {$try_srcdir}$try" >&2
if test $try != $xsrcdir$name_base/$x && test -d $try_srcdir$try;
then
+ # If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
+ # ieee754/dbl-64.
+ if test "$use_dbl_wrap" = "0"; then
+ case $try in
+ sysdeps/ieee754/dbl-64)
+ implied="$implied sysdeps/ieee754/dbl-wrap" ;;
+ sysdeps/ieee754/ldbl-*)
+ implied="$implied sysdeps/ieee754/ldbl-wrap" ;;
+ esac
+ fi
implied="$implied $try"
found=yes
case "$sysnames_add_ons" in
diff --git a/configure.in b/configure.in
index 301e4fc..9bdadd3 100644
--- a/configure.in
+++ b/configure.in
@@ -758,6 +758,10 @@ if test "$elf" = yes; then
sysnames="`echo $elf_dirs | sed -e 's,//,/,g'` $sysnames"
fi
+# Peek into option-groups.config to check if sysdeps/ieee754/[l]dbl-wrap needs
+# to be included into $sysnames.
+grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config > /dev/null 2>&1
+use_dbl_wrap=$?
# Expand the list of system names into a full list of directories
# from each element's parent name and Implies file (if present).
@@ -791,6 +795,14 @@ while test $# -gt 0; do
for x in $implied_candidate; do
found=no
if test -d $xsrcdir$name_base/$x; then
+ # If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
+ # ieee754/dbl-64.
+ if test "$use_dbl_wrap" = "0"; then
+ case $x in
+ ieee754/dbl-64) implied="$implied $name_base/ieee754/dbl-wrap" ;;
+ ieee754/ldbl-*) implied="$implied $name_base/ieee754/ldbl-wrap" ;;
+ esac
+ fi
implied="$implied $name_base/$x";
found=yes
fi
@@ -804,6 +816,16 @@ while test $# -gt 0; do
echo "[DEBUG]: $name implied $x try($d) {$try_srcdir}$try" >&2
if test $try != $xsrcdir$name_base/$x && test -d $try_srcdir$try;
then
+ # If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
+ # ieee754/dbl-64.
+ if test "$use_dbl_wrap" = "0"; then
+ case $try in
+ sysdeps/ieee754/dbl-64)
+ implied="$implied sysdeps/ieee754/dbl-wrap" ;;
+ sysdeps/ieee754/ldbl-*)
+ implied="$implied sysdeps/ieee754/ldbl-wrap" ;;
+ esac
+ fi
implied="$implied $try"
found=yes
case "$sysnames_add_ons" in
diff --git a/math/Makefile b/math/Makefile
index c263801..3d5a00c 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -90,9 +90,11 @@ long-c-yes = $(calls:=l)
distribute += $(filter-out $(generated),$(long-m-yes:=.c) $(long-c-yes:=.c))
# Rules for the test suite.
-tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
+tests = test-matherr test-fenv basic-test \
test-misc test-fpucw tst-definitions test-tgmath test-tgmath-ret \
- bug-nextafter bug-nexttoward bug-tgmath1 test-tgmath-int test-tgmath2
+ bug-nextafter bug-nexttoward bug-tgmath1 test-tgmath-int test-tgmath2 \
+ test-dbl-wrap
+tests-$(OPTION_EGLIBC_LIBM_BIG) += atest-exp atest-sincos atest-exp2
# We do the `long double' tests only if this data type is available and
# distinct from `double'.
test-longdouble-yes = test-ldouble test-ildoubl
@@ -114,9 +116,12 @@ ulps-file = $(firstword $(wildcard $(sysdirs:%=%/libm-test-ulps)))
$(addprefix $(objpfx), $(libm-tests-generated)): $(objpfx)libm-test.stmp
+ifeq (n,$(OPTION_EGLIBC_LIBM_BIG))
+default_ulp = -d 1
+endif
$(objpfx)libm-test.stmp: $(ulps-file) libm-test.inc gen-libm-test.pl
$(make-target-directory)
- $(PERL) gen-libm-test.pl -u $< -o "$(objpfx)"
+ $(PERL) gen-libm-test.pl -u $< $(default_ulp) -o "$(objpfx)"
@echo > $@
$(objpfx)test-float.o: $(objpfx)libm-test.stmp
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index 0b0b8ca..b916506 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -48,7 +48,7 @@ use vars qw (%results);
use vars qw (@tests @functions);
use vars qw ($count);
use vars qw (%beautify @all_floats);
-use vars qw ($output_dir $ulps_file);
+use vars qw ($output_dir $ulps_file $default_ulp);
# all_floats is sorted and contains all recognised float types
@all_floats = ('double', 'float', 'idouble',
@@ -93,11 +93,12 @@ use vars qw ($output_dir $ulps_file);
# h: help
# o: output-directory
# n: generate new ulps file
-use vars qw($opt_u $opt_h $opt_o $opt_n);
-getopts('u:o:nh');
+use vars qw($opt_u $opt_h $opt_o $opt_n $opt_d);
+getopts('u:o:d:nh');
$ulps_file = 'libm-test-ulps';
$output_dir = '';
+$default_ulp = '0';
if ($opt_h) {
print "Usage: gen-libm-test.pl [OPTIONS]\n";
@@ -105,11 +106,13 @@ if ($opt_h) {
print " -o DIR directory where generated files will be placed\n";
print " -n only generate sorted file NewUlps from libm-test-ulps\n";
print " -u FILE input file with ulps\n";
+ print " -d NUM set the default value for ulp to NUM\n";
exit 0;
}
$ulps_file = $opt_u if ($opt_u);
$output_dir = $opt_o if ($opt_o);
+$default_ulp = $opt_d if ($opt_d);
$input = "libm-test.inc";
$output = "${output_dir}libm-test.c";
@@ -463,7 +466,11 @@ sub generate_testfile {
if (exists $results{$fct}{'has_ulps'}) {
$line .= "DELTA$fct";
} else {
- $line .= '0';
+ if ($type eq 'complex') {
+ $line .= "BUILD_COMPLEX ($default_ulp, $default_ulp)";
+ } else {
+ $line .= "$default_ulp";
+ }
}
if (exists $results{$fct}{'has_fails'}) {
$line .= ", FAIL$fct";
@@ -645,19 +652,19 @@ sub get_ulps {
# Return 0 instead of BUILD_COMPLEX (0,0)
if (!exists $results{$test}{'real'}{'ulp'}{$float} &&
!exists $results{$test}{'imag'}{'ulp'}{$float}) {
- return "0";
+ return "BUILD_COMPLEX ($default_ulp, $default_ulp)";
}
$res = 'BUILD_COMPLEX (';
$res .= (exists $results{$test}{'real'}{'ulp'}{$float}
- ? $results{$test}{'real'}{'ulp'}{$float} : "0");
+ ? $results{$test}{'real'}{'ulp'}{$float} : "$default_ulp");
$res .= ', ';
$res .= (exists $results{$test}{'imag'}{'ulp'}{$float}
- ? $results{$test}{'imag'}{'ulp'}{$float} : "0");
+ ? $results{$test}{'imag'}{'ulp'}{$float} : "$default_ulp");
$res .= ')';
return $res;
}
return (exists $results{$test}{'normal'}{'ulp'}{$float}
- ? $results{$test}{'normal'}{'ulp'}{$float} : "0");
+ ? $results{$test}{'normal'}{'ulp'}{$float} : "$default_ulp");
}
sub get_failure {
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 260d3ec..235fbaa 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -128,6 +128,7 @@
#include <stdio.h>
#include <string.h>
#include <argp.h>
+#include <gnu/option-groups.h>
/* Possible exceptions */
#define NO_EXCEPTION 0x0
@@ -188,8 +189,15 @@ static FLOAT max_error, real_max_error, imag_max_error;
__retval; })
+#if __OPTION_EGLIBC_LIBM_BIG
#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \
(LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1))
+#else
+/* Reduce precision to which the results are checked against
+ expected values. */
+#define MANT_DIG CHOOSE ((FLT_MANT_DIG-3), (FLT_MANT_DIG-4), (FLT_MANT_DIG-1), \
+ (FLT_MANT_DIG-3), (FLT_MANT_DIG-4), (FLT_MANT_DIG-1))
+#endif
static void
init_max_error (void)
@@ -2483,7 +2491,12 @@ erfc_test (void)
#ifdef TEST_LDOUBLE
/* The result can only be represented in long double. */
# if LDBL_MIN_10_EXP < -319
+# if __OPTION_EGLIBC_LIBM_BIG
TEST_f_f (erfc, 27.0L, 0.523704892378925568501606768284954709e-318L);
+# else
+ /* ldbl-wrap uses single-precision erfc, so it can't handle e-318 values. */
+ TEST_f_f (erfc, 27.0L, 0.0L);
+# endif
# endif
#endif
diff --git a/math/test-dbl-wrap.c b/math/test-dbl-wrap.c
new file mode 100644
index 0000000..c5dfe2d
--- /dev/null
+++ b/math/test-dbl-wrap.c
@@ -0,0 +1,108 @@
+#include <math.h>
+#include <stdio.h>
+
+#define N 4
+
+int
+main (void)
+{
+ int i;
+ int result = 0;
+
+ const double eps = 0.01, pi = 3.14;
+ const double sin_data[N][2]
+ = {{0.0, 0.0}, {pi / 6, 0.5}, {pi / 4, 0.707}, {pi / 3, 0.866}};
+ const double exp_data[N][2]
+ = {{0.0, 1.0}, {0.5, 1.649}, {1.0, 2.718}, {2.718, 15.150}};
+
+ for (i = 0; i < N; ++i)
+ {
+ double x, y;
+ double s1, c1, t1, e1;
+ double s2, c2, t2, as2, ac2, at2, e2, l2;
+
+ x = sin_data[i][0];
+ s1 = sin_data[i][1];
+ c1 = sqrt (1 - s1 * s1);
+ t1 = s1 / c1;
+
+ s2 = sin (x);
+ c2 = cos (x);
+ t2 = tan (x);
+ as2 = asin (s1);
+ ac2 = acos (c1);
+ at2 = atan (t1);
+
+ y = exp_data[i][0];
+ e1 = exp_data[i][1];
+
+ e2 = exp (y);
+ l2 = log (e1);
+
+ if (fabs (s1 - s2) > eps)
+ {
+ result |= 1;
+#if PRINT
+ printf ("sin(%.3lf) = %.3lf\n", x, s2);
+#endif
+ }
+
+ if (fabs (c1 - c2) > eps)
+ {
+ result |= 2;
+#if PRINT
+ printf ("cos(%.3lf) = %.3lf\n", x, c2);
+#endif
+ }
+
+ if (fabs (t1 - t2) > eps)
+ {
+ result |= 4;
+#if PRINT
+ printf ("tan(%.3lf) = %.3lf\n", x, t2);
+#endif
+ }
+
+ if (fabs (x - as2) > eps)
+ {
+ result |= 8;
+#if PRINT
+ printf ("asin(%.3lf) = %.3lf\n", s1, as2);
+#endif
+ }
+
+ if (fabs (x - ac2) > eps)
+ {
+ result |= 16;
+#if PRINT
+ printf ("acos(%.3lf) = %.3lf\n", c1, ac2);
+#endif
+ }
+
+ if (fabs (x - at2) > eps)
+ {
+ result |= 32;
+#if PRINT
+ printf ("atan(%.3lf) = %.3lf\n", t1, at2);
+#endif
+ }
+
+ if (fabs (e1 - e2) > eps)
+ {
+ result |= 64;
+#if PRINT
+ printf ("exp(%.3lf) = %.3lf\n", y, e2);
+#endif
+ }
+
+ if (fabs (y - l2) > eps)
+ {
+ result |= 128;
+#if PRINT
+ printf ("log(%.3lf) = %.3lf\n", e1, l2);
+#endif
+ }
+ }
+
+ return result;
+}
diff --git a/option-groups.def b/option-groups.def
index 26ef4bb..940b625 100644
--- a/option-groups.def
+++ b/option-groups.def
@@ -434,6 +434,19 @@ config OPTION_EGLIBC_LIBM
group, you will not be able to build 'libstdc++' against the
resulting EGLIBC installation.
+config OPTION_EGLIBC_LIBM_BIG
+ bool "Math library size"
+ help
+ This option group enables default configuration of the math library.
+ Not selecting this option group removes most of the extended and
+ double precision math functions and replaces them with wrappers
+ to the single precision couterparts.
+ Doing so greatly degrades quality of calculations carried
+ out by the functions of the math library, but also significantly
+ reduces the size of the libm.
+ This option group is useful for systems that do not rely on precise
+ floating point math.
+
config OPTION_EGLIBC_LOCALES
bool "Locale definitions"
help
diff --git a/option-groups.defaults b/option-groups.defaults
index 4653e64..8cc7e08 100644
--- a/option-groups.defaults
+++ b/option-groups.defaults
@@ -24,6 +24,7 @@ OPTION_EGLIBC_FTRAVERSE = y
OPTION_EGLIBC_GETLOGIN = y
OPTION_EGLIBC_INET = y
OPTION_EGLIBC_LIBM = y
+OPTION_EGLIBC_LIBM_BIG = y
OPTION_EGLIBC_LOCALES = y
OPTION_EGLIBC_LOCALE_CODE = y
OPTION_EGLIBC_NIS = y
diff --git a/sysdeps/ieee754/dbl-wrap/dbl-wrap.h b/sysdeps/ieee754/dbl-wrap/dbl-wrap.h
new file mode 100644
index 0000000..b381828
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/dbl-wrap.h
@@ -0,0 +1,2 @@
+typedef float wrap_type_t;
+#define WRAP_FUNC(func) func ## f
diff --git a/sysdeps/ieee754/dbl-wrap/dosincos.c b/sysdeps/ieee754/dbl-wrap/dosincos.c
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/dosincos.c
@@ -0,0 +1 @@
+/* empty */
diff --git a/sysdeps/ieee754/dbl-wrap/e_asin.c b/sysdeps/ieee754/dbl-wrap/e_asin.c
new file mode 100644
index 0000000..86416b3
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/e_asin.c
@@ -0,0 +1,17 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_asin) (wrap_type_t);
+
+double
+__ieee754_asin (double x)
+{
+ return (double) WRAP_FUNC (__ieee754_asin) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__ieee754_acos) (wrap_type_t);
+
+double
+__ieee754_acos (double x)
+{
+ return (double) WRAP_FUNC (__ieee754_acos) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/dbl-wrap/e_atan2.c b/sysdeps/ieee754/dbl-wrap/e_atan2.c
new file mode 100644
index 0000000..4bcb058
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/e_atan2.c
@@ -0,0 +1,9 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_atan2) (wrap_type_t, wrap_type_t);
+
+double
+__ieee754_atan2 (double y, double x)
+{
+ return (double) WRAP_FUNC (__ieee754_atan2) ((wrap_type_t) y, (wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/dbl-wrap/e_exp.c b/sysdeps/ieee754/dbl-wrap/e_exp.c
new file mode 100644
index 0000000..df3447e
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/e_exp.c
@@ -0,0 +1,9 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_exp) (wrap_type_t);
+
+double
+__ieee754_exp (double x)
+{
+ return (double) WRAP_FUNC (__ieee754_exp) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/dbl-wrap/e_exp2.c b/sysdeps/ieee754/dbl-wrap/e_exp2.c
new file mode 100644
index 0000000..121c297
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/e_exp2.c
@@ -0,0 +1,9 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_exp2) (wrap_type_t);
+
+double
+__ieee754_exp2 (double x)
+{
+ return (double) WRAP_FUNC (__ieee754_exp2) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/dbl-wrap/e_log.c b/sysdeps/ieee754/dbl-wrap/e_log.c
new file mode 100644
index 0000000..557775f
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/e_log.c
@@ -0,0 +1,8 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_log) (wrap_type_t);
+
+double __ieee754_log (double x)
+{
+ return (double) WRAP_FUNC (__ieee754_log) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/dbl-wrap/e_pow.c b/sysdeps/ieee754/dbl-wrap/e_pow.c
new file mode 100644
index 0000000..0f74d51
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/e_pow.c
@@ -0,0 +1,9 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_pow) (wrap_type_t, wrap_type_t);
+
+double
+__ieee754_pow (double x, double y)
+{
+ return (double) WRAP_FUNC (__ieee754_pow) ((wrap_type_t) x, (wrap_type_t) y);
+}
diff --git a/sysdeps/ieee754/dbl-wrap/s_atan.c b/sysdeps/ieee754/dbl-wrap/s_atan.c
new file mode 100644
index 0000000..5099dd6
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/s_atan.c
@@ -0,0 +1,13 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (atan) (wrap_type_t);
+
+double
+atan (double x)
+{
+ return (double) WRAP_FUNC (atan) ((wrap_type_t) x);
+}
+
+#ifdef NO_LONG_DOUBLE
+weak_alias (atan, atanl)
+#endif
diff --git a/sysdeps/ieee754/dbl-wrap/s_sin.c b/sysdeps/ieee754/dbl-wrap/s_sin.c
new file mode 100644
index 0000000..fbe2a97
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/s_sin.c
@@ -0,0 +1,27 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__sin) (wrap_type_t);
+
+double
+__sin (double x)
+{
+ return (double) WRAP_FUNC (__sin) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__cos) (wrap_type_t);
+
+double
+__cos (double x)
+{
+ return (double) WRAP_FUNC (__cos) ((wrap_type_t) x);
+}
+
+weak_alias (__cos, cos)
+weak_alias (__sin, sin)
+
+#ifdef NO_LONG_DOUBLE
+strong_alias (__sin, __sinl)
+weak_alias (__sin, sinl)
+strong_alias (__cos, __cosl)
+weak_alias (__cos, cosl)
+#endif
diff --git a/sysdeps/ieee754/dbl-wrap/s_tan.c b/sysdeps/ieee754/dbl-wrap/s_tan.c
new file mode 100644
index 0000000..ddc99af
--- /dev/null
+++ b/sysdeps/ieee754/dbl-wrap/s_tan.c
@@ -0,0 +1,13 @@
+#include "dbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (tan) (wrap_type_t);
+
+double
+tan (double x)
+{
+ return (double) WRAP_FUNC (tan) ((wrap_type_t) x);
+}
+
+#ifdef NO_LONG_DOUBLE
+weak_alias (tan, tanl)
+#endif
diff --git a/sysdeps/ieee754/ldbl-128/s_erfl.c b/sysdeps/ieee754/ldbl-128/s_erfl.c
index e6983ec..03ede5d 100644
--- a/sysdeps/ieee754/ldbl-128/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-128/s_erfl.c
@@ -98,6 +98,9 @@
#include "math.h"
#include "math_private.h"
+#include <gnu/option-groups.h>
+
+#if __OPTION_EGLIBC_LIBM_BIG
/* Evaluate P[n] x^n + P[n-1] x^(n-1) + ... + P[0] */
@@ -948,4 +951,9 @@ weak_alias (__erfl, erfl)
}
}
+#else /* !__OPTION_EGLIBC_LIBM_BIG */
+# include <sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c>
+weak_alias (__erfl, erfl)
+#endif /* __OPTION_EGLIBC_LIBM_BIG */
+
weak_alias (__erfcl, erfcl)
diff --git a/sysdeps/ieee754/ldbl-128/s_log1pl.c b/sysdeps/ieee754/ldbl-128/s_log1pl.c
index defbe76..4480dc9 100644
--- a/sysdeps/ieee754/ldbl-128/s_log1pl.c
+++ b/sysdeps/ieee754/ldbl-128/s_log1pl.c
@@ -55,6 +55,9 @@
#include "math.h"
#include "math_private.h"
+#include <gnu/option-groups.h>
+
+#if __OPTION_EGLIBC_LIBM_BIG
/* Coefficients for log(1+x) = x - x^2 / 2 + x^3 P(x)/Q(x)
* 1/sqrt(2) <= 1+x < sqrt(2)
@@ -246,4 +249,8 @@ __log1pl (long double xm1)
return (z);
}
+#else /* !__OPTION_EGLIBC_LIBM_BIG */
+# include <sysdeps/ieee754/ldbl-wrap/s_log1pl-wrap.c>
+#endif /* __OPTION_EGLIBC_LIBM_BIG */
+
weak_alias (__log1pl, log1pl)
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_erfl.c b/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
index 02b450e..f40c783 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
@@ -99,6 +99,9 @@
#include "math.h"
#include "math_private.h"
#include <math_ldbl_opt.h>
+#include <gnu/option-groups.h>
+
+#if __OPTION_EGLIBC_LIBM_BIG
/* Evaluate P[n] x^n + P[n-1] x^(n-1) + ... + P[0] */
@@ -955,4 +958,9 @@ long_double_symbol (libm, __erfl, erfl);
}
}
+#else /* !__OPTION_EGLIBC_LIBM_BIG */
+# include <sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c>
+long_double_symbol (libm, __erfl, erfl);
+#endif /* __OPTION_EGLIBC_LIBM_BIG */
+
long_double_symbol (libm, __erfcl, erfcl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c b/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c
index 5ccf541..30c1a6b 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c
@@ -56,6 +56,9 @@
#include "math.h"
#include "math_private.h"
#include <math_ldbl_opt.h>
+#include <gnu/option-groups.h>
+
+#if __OPTION_EGLIBC_LIBM_BIG
/* Coefficients for log(1+x) = x - x^2 / 2 + x^3 P(x)/Q(x)
* 1/sqrt(2) <= 1+x < sqrt(2)
@@ -248,4 +251,8 @@ __log1pl (long double xm1)
return (z);
}
+#else /* !__OPTION_EGLIBC_LIBM_BIG */
+# include <sysdeps/ieee754/ldbl-wrap/s_log1pl-wrap.c>
+#endif /* __OPTION_EGLIBC_LIBM_BIG */
+
long_double_symbol (libm, __log1pl, log1pl);
diff --git a/sysdeps/ieee754/ldbl-96/s_erfl.c b/sysdeps/ieee754/ldbl-96/s_erfl.c
index 7406c36..957fd4b 100644
--- a/sysdeps/ieee754/ldbl-96/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-96/s_erfl.c
@@ -106,6 +106,9 @@
#include "math.h"
#include "math_private.h"
+#include <gnu/option-groups.h>
+
+#if __OPTION_EGLIBC_LIBM_BIG
#ifdef __STDC__
static const long double
@@ -451,4 +454,9 @@ weak_alias (__erfl, erfl)
}
}
+#else /* !__OPTION_EGLIBC_LIBM_BIG */
+# include <sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c>
+weak_alias (__erfl, erfl)
+#endif /* __OPTION_EGLIBC_LIBM_BIG */
+
weak_alias (__erfcl, erfcl)
diff --git a/sysdeps/ieee754/ldbl-opt/s_atan.c b/sysdeps/ieee754/ldbl-opt/s_atan.c
index 5fbd5e6..81d325e 100644
--- a/sysdeps/ieee754/ldbl-opt/s_atan.c
+++ b/sysdeps/ieee754/ldbl-opt/s_atan.c
@@ -1,5 +1,10 @@
#include <math_ldbl_opt.h>
-#include <sysdeps/ieee754/dbl-64/s_atan.c>
+#include <gnu/option-groups.h>
+#if __OPTION_EGLIBC_LIBM_BIG
+# include <sysdeps/ieee754/dbl-64/s_atan.c>
+#else
+# include <sysdeps/ieee754/dbl-wrap/s_atan.c>
+#endif
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
compat_symbol (libm, atan, atanl, GLIBC_2_0);
#endif
diff --git a/sysdeps/ieee754/ldbl-opt/s_sin.c b/sysdeps/ieee754/ldbl-opt/s_sin.c
index a11d5a3..381d24d 100644
--- a/sysdeps/ieee754/ldbl-opt/s_sin.c
+++ b/sysdeps/ieee754/ldbl-opt/s_sin.c
@@ -1,9 +1,14 @@
/* dbl-64/s_sin.c uses NAN and sincos identifiers internally. */
#define sincos sincos_disable
#include <math_ldbl_opt.h>
+#include <gnu/option-groups.h>
#undef NAN
#undef sincos
-#include <sysdeps/ieee754/dbl-64/s_sin.c>
+#if __OPTION_EGLIBC_LIBM_BIG
+# include <sysdeps/ieee754/dbl-64/s_sin.c>
+#else
+# include <sysdeps/ieee754/dbl-wrap/s_sin.c>
+#endif
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
compat_symbol (libm, __sin, sinl, GLIBC_2_0);
compat_symbol (libm, __cos, cosl, GLIBC_2_0);
diff --git a/sysdeps/ieee754/ldbl-opt/s_tan.c b/sysdeps/ieee754/ldbl-opt/s_tan.c
index 6b0fec0..23b45ad 100644
--- a/sysdeps/ieee754/ldbl-opt/s_tan.c
+++ b/sysdeps/ieee754/ldbl-opt/s_tan.c
@@ -1,5 +1,10 @@
#include <math_ldbl_opt.h>
-#include <sysdeps/ieee754/dbl-64/s_tan.c>
+#include <gnu/option-groups.h>
+#if __OPTION_EGLIBC_LIBM_BIG
+# include <sysdeps/ieee754/dbl-64/s_tan.c>
+#else
+# include <sysdeps/ieee754/dbl-wrap/s_tan.c>
+#endif
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
compat_symbol (libm, tan, tanl, GLIBC_2_0);
#endif
diff --git a/sysdeps/ieee754/ldbl-wrap/e_acosl.c b/sysdeps/ieee754/ldbl-wrap/e_acosl.c
new file mode 100644
index 0000000..ab0c879
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_acosl.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_acos) (wrap_type_t);
+
+long double
+__ieee754_acosl (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_acos) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_asinl.c b/sysdeps/ieee754/ldbl-wrap/e_asinl.c
new file mode 100644
index 0000000..71ee4f9
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_asinl.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_asin) (wrap_type_t);
+
+long double
+__ieee754_asinl (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_asin) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_expl.c b/sysdeps/ieee754/ldbl-wrap/e_expl.c
new file mode 100644
index 0000000..75a5343
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_expl.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_exp) (wrap_type_t);
+
+long double
+__ieee754_expl (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_exp) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_j0l.c b/sysdeps/ieee754/ldbl-wrap/e_j0l.c
new file mode 100644
index 0000000..a213d70
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_j0l.c
@@ -0,0 +1,17 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_j0) (wrap_type_t);
+
+long double
+__ieee754_j0l (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_j0) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__ieee754_y0) (wrap_type_t);
+
+long double
+__ieee754_y0l (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_y0) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_j1l.c b/sysdeps/ieee754/ldbl-wrap/e_j1l.c
new file mode 100644
index 0000000..b2c7de1
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_j1l.c
@@ -0,0 +1,17 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_j1) (wrap_type_t);
+
+long double
+__ieee754_j1l (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_j1) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__ieee754_y1) (wrap_type_t);
+
+long double
+__ieee754_y1l (long double x)
+{
+ return (long double) WRAP_FUNC (__ieee754_y1) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c b/sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c
new file mode 100644
index 0000000..80d6153
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC2 (__ieee754_lgamma, _r) (wrap_type_t, int *);
+
+long double
+__ieee754_lgammal_r (long double x, int *s)
+{
+ return (long double) WRAP_FUNC2 (__ieee754_lgamma, _r) ((wrap_type_t) x, s);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_powl.c b/sysdeps/ieee754/ldbl-wrap/e_powl.c
new file mode 100644
index 0000000..ef779ce
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_powl.c
@@ -0,0 +1,10 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_pow) (wrap_type_t, wrap_type_t);
+
+long double
+__ieee754_powl (long double x, long double y)
+{
+ return (long double) WRAP_FUNC (__ieee754_pow) ((wrap_type_t) x,
+ (wrap_type_t) y);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h b/sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h
new file mode 100644
index 0000000..36aeffe
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h
@@ -0,0 +1,3 @@
+typedef float wrap_type_t;
+#define WRAP_FUNC(func) func ## f
+#define WRAP_FUNC2(func, suffix) func ## f ## suffix
diff --git a/sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c b/sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c
new file mode 100644
index 0000000..837f97b
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/s_erfl-wrap.c
@@ -0,0 +1,17 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__erf) (wrap_type_t);
+
+long double
+__erfl (long double x)
+{
+ return (long double) WRAP_FUNC (__erf) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__erfc) (wrap_type_t);
+
+long double
+__erfcl (long double x)
+{
+ return (long double) WRAP_FUNC (__erfc) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/s_log1pl-wrap.c b/sysdeps/ieee754/ldbl-wrap/s_log1pl-wrap.c
new file mode 100644
index 0000000..d531853
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/s_log1pl-wrap.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__log1p) (wrap_type_t);
+
+long double
+__log1pl (long double x)
+{
+ return (long double) WRAP_FUNC (__log1p) ((wrap_type_t) x);
+}