mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-09 04:11:27 +08:00
55a38f8236
TS 18661-1 defines llogb functions that are like ilogb except that they return long int instead of int. Corresponding FP_LLOGB* macros are defined, whose values are required to have the obvious correspondence to those of the FP_ILOGB* macros. This patch implements these functions and macros for glibc. llogb uses the type-generic infrastructure, with an implementation similar to the wrapper for ilogb but with additional conversion from FP_ILOGB* to FP_LLOGB*; this approach avoids needing to modify or duplicate any of the architecture-specific ilogb implementations. Tests are also based on those for ilogb. Ideally the llogb functions would alias the ilogb ones when long is 32-bit, but such aliasing requires the associated header declarations of the different-type alias to be hidden, typically by defining macros before including the header (see e.g. how sysdeps/ieee754/dbl-64/wordsize-64/s_llround.c defines lround to __hidden_lround before including <math.h>). The infrastructure for type-generic function implementations does not support defining such macros at present (since C code can't define a macro whose name is determined by other macros). So this patch leaves them as separate functions (similar to e.g. scalbln and scalbn being separate in such a case as well), but with the remapping of FP_ILOGB* to FP_LLOGB* conditioned out in the case where it would be the identity map. Tested for x86_64, x86, mips64 and powerpc. * math/bits/mathcalls.h [__GLIBC_USE (IEC_60559_BFP_EXT)] (llogb): New declaration. * math/tgmath.h [__GLIBC_USE (IEC_60559_BFP_EXT)] (llogb): New macro. * math/math.h [__GLIBC_USE (IEC_60559_BFP_EXT)] (__FP_LONG_MAX): New macro. [__GLIBC_USE (IEC_60559_BFP_EXT)] (FP_LLOGB0): Likewise. [__GLIBC_USE (IEC_60559_BFP_EXT)] (FP_LLOGBNAN): Likewise. * math/Versions (llogb): New libm symbol at version GLIBC_2.25. (llogbf): Likewise. (llogbl): Likewise. * math/Makefile (gen-libm-calls): Add w_llogbF. (tests): Add test-fp-llogb-constants. * math/w_llogb_template.c: New file. Based on math/w_ilogb_template.c. * math/libm-test.inc (llogb_test_data): New array. (llogb_test): New function. (main): Call llogb_test. * math/test-fp-llogb-constants.c: New file. Based on math/test-fp-ilogb-constants.c. * math/test-tgmath-ret.c (llogb): New CHECK_RET_CONST call. (do_test): Call check_return_llogb. * math/test-tgmath.c (NCALLS): Increase to 126. (F(compile_test)): Call llogb. (F(llogb)): New function. * manual/math.texi (Exponents and Logarithms): Document llogb, llogbf, llogbl, FP_LLOGB0 and FP_LLOGBNAN. * manual/libm-err-tab.pl (@all_functions): Add llogb. * sysdeps/ieee754/ldbl-opt/nldbl-llogb.c: New file. * sysdeps/ieee754/ldbl-opt/w_llogbl.c: Likewise. * sysdeps/ieee754/ldbl-opt/Makefile (libnldbl-calls): Add llogb. (CFLAGS-nldbl-llogb.c): New variable. * sysdeps/nacl/libm.abilist: Update. * sysdeps/unix/sysv/linux/aarch64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/alpha/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/arm/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/hppa/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/i386/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/ia64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/microblaze/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/mips/mips32/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/nios2/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/sh/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/x86_64/64/libm.abilist: Likewise. * sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist: Likewise.
217 lines
6.4 KiB
Perl
Executable File
217 lines
6.4 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
# Copyright (C) 1999-2016 Free Software Foundation, Inc.
|
|
# This file is part of the GNU C Library.
|
|
# Contributed by Andreas Jaeger <aj@suse.de>, 1999.
|
|
|
|
# The GNU C Library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
# The GNU C Library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with the GNU C Library; if not, see
|
|
# <http://www.gnu.org/licenses/>.
|
|
|
|
# Information about tests are stored in: %results
|
|
# $results{$test}{"type"} is the result type, e.g. normal or complex.
|
|
# In the following description $platform, $type and $float are:
|
|
# - $platform is the used platform
|
|
# - $type is either "normal", "real" (for the real part of a complex number)
|
|
# or "imag" (for the imaginary part # of a complex number).
|
|
# - $float is either of float, ifloat, double, idouble, ldouble, ildouble;
|
|
# It represents the underlying floating point type (float, double or long
|
|
# double) and if inline functions (the leading i stands for inline)
|
|
# are used.
|
|
# $results{$test}{$platform}{$type}{$float} is defined and has a delta
|
|
# or 'fail' as value.
|
|
|
|
use File::Find;
|
|
|
|
use strict;
|
|
|
|
use vars qw ($sources @platforms %pplatforms);
|
|
use vars qw (%results @all_floats %suffices @all_functions);
|
|
|
|
|
|
# all_floats is in output order and contains all recognised float types that
|
|
# we're going to output
|
|
@all_floats = ('float', 'double', 'ldouble');
|
|
%suffices =
|
|
( 'float' => 'f',
|
|
'double' => '',
|
|
'ldouble' => 'l'
|
|
);
|
|
|
|
# Pretty description of platform
|
|
%pplatforms = ();
|
|
|
|
@all_functions =
|
|
( "acos", "acosh", "asin", "asinh", "atan", "atanh",
|
|
"atan2", "cabs", "cacos", "cacosh", "carg", "casin", "casinh",
|
|
"catan", "catanh", "cbrt", "ccos", "ccosh", "ceil", "cexp", "cimag",
|
|
"clog", "clog10", "conj", "copysign", "cos", "cosh", "cpow", "cproj",
|
|
"creal", "csin", "csinh", "csqrt", "ctan", "ctanh", "erf", "erfc",
|
|
"exp", "exp10", "exp2", "expm1", "fabs", "fdim", "floor", "fma",
|
|
"fmax", "fmin", "fmod", "frexp", "gamma", "hypot",
|
|
"ilogb", "j0", "j1", "jn", "lgamma", "llogb", "lrint",
|
|
"llrint", "log", "log10", "log1p", "log2", "logb", "lround",
|
|
"llround", "modf", "nearbyint", "nextafter", "nextdown", "nexttoward",
|
|
"nextup", "pow", "remainder", "remquo", "rint", "round", "scalb",
|
|
"scalbn", "sin", "sincos", "sinh", "sqrt", "tan", "tanh", "tgamma",
|
|
"trunc", "y0", "y1", "yn" );
|
|
# canonicalize, fpclassify, getpayload, iscanonical, isnormal,
|
|
# isfinite, isinf, isnan, issignaling, issubnormal, iszero, signbit,
|
|
# iseqsig, isgreater, isgreaterequal, isless, islessequal,
|
|
# islessgreater, isunordered, setpayload, setpayloadsig,
|
|
# totalorder, totalordermag
|
|
# are not tabulated.
|
|
|
|
if ($#ARGV == 0) {
|
|
$sources = $ARGV[0];
|
|
} else {
|
|
$sources = '/usr/src/cvs/libc';
|
|
}
|
|
|
|
find (\&find_files, $sources);
|
|
|
|
@platforms = sort by_platforms @platforms;
|
|
|
|
&print_all;
|
|
|
|
sub find_files {
|
|
if ($_ eq 'libm-test-ulps') {
|
|
# print "Parsing $File::Find::name\n";
|
|
push @platforms, $File::Find::dir;
|
|
my ($file, $name);
|
|
$file = "${File::Find::name}-name";
|
|
open NAME, $file or die ("Can't open $file: $!");
|
|
$name = <NAME>;
|
|
chomp $name;
|
|
close NAME;
|
|
$pplatforms{$File::Find::dir} = $name;
|
|
&parse_ulps ($File::Find::name, $File::Find::dir);
|
|
}
|
|
}
|
|
|
|
# Parse ulps file
|
|
sub parse_ulps {
|
|
my ($file, $platform) = @_;
|
|
my ($test, $type, $float, $eps);
|
|
|
|
# $type has the following values:
|
|
# "normal": No complex variable
|
|
# "real": Real part of complex result
|
|
# "imag": Imaginary part of complex result
|
|
open ULP, $file or die ("Can't open $file: $!");
|
|
while (<ULP>) {
|
|
chop;
|
|
# ignore comments and empty lines
|
|
next if /^#/;
|
|
next if /^\s*$/;
|
|
if (/^Function: /) {
|
|
if (/Real part of/) {
|
|
s/Real part of //;
|
|
$type = 'real';
|
|
} elsif (/Imaginary part of/) {
|
|
s/Imaginary part of //;
|
|
$type = 'imag';
|
|
} else {
|
|
$type = 'normal';
|
|
}
|
|
($test) = ($_ =~ /^Function:\s*\"([a-zA-Z0-9_]+)\"/);
|
|
next;
|
|
}
|
|
if (/^i?(float|double|ldouble):/) {
|
|
($float, $eps) = split /\s*:\s*/,$_,2;
|
|
if ($eps eq 'fail') {
|
|
$results{$test}{$platform}{$type}{$float} = 'fail';
|
|
} elsif ($eps eq "0") {
|
|
# ignore
|
|
next;
|
|
} elsif (!exists $results{$test}{$platform}{$type}{$float}
|
|
|| $results{$test}{$platform}{$type}{$float} ne 'fail') {
|
|
$results{$test}{$platform}{$type}{$float} = $eps;
|
|
}
|
|
if ($type =~ /^real|imag$/) {
|
|
$results{$test}{'type'} = 'complex';
|
|
} elsif ($type eq 'normal') {
|
|
$results{$test}{'type'} = 'normal';
|
|
}
|
|
next;
|
|
}
|
|
print "Skipping unknown entry: `$_'\n";
|
|
}
|
|
close ULP;
|
|
}
|
|
|
|
sub get_value {
|
|
my ($fct, $platform, $type, $float) = @_;
|
|
|
|
return (exists $results{$fct}{$platform}{$type}{$float}
|
|
? $results{$fct}{$platform}{$type}{$float} : "0");
|
|
}
|
|
|
|
sub print_platforms {
|
|
my (@p) = @_;
|
|
my ($fct, $platform, $float, $first, $i, $platform_no, $platform_total);
|
|
|
|
print '@multitable {nexttowardf} ';
|
|
foreach (@p) {
|
|
print ' {1000 + i 1000}';
|
|
}
|
|
print "\n";
|
|
|
|
print '@item Function ';
|
|
foreach (@p) {
|
|
print ' @tab ';
|
|
print $pplatforms{$_};
|
|
}
|
|
print "\n";
|
|
|
|
|
|
foreach $fct (@all_functions) {
|
|
foreach $float (@all_floats) {
|
|
print "\@item $fct$suffices{$float} ";
|
|
foreach $platform (@p) {
|
|
print ' @tab ';
|
|
if (exists $results{$fct}{$platform}{'normal'}{$float}
|
|
|| exists $results{$fct}{$platform}{'real'}{$float}
|
|
|| exists $results{$fct}{$platform}{'imag'}{$float}) {
|
|
if ($results{$fct}{'type'} eq 'complex') {
|
|
print &get_value ($fct, $platform, 'real', $float),
|
|
' + i ', &get_value ($fct, $platform, 'imag', $float);
|
|
} else {
|
|
print $results{$fct}{$platform}{'normal'}{$float};
|
|
}
|
|
} else {
|
|
print '-';
|
|
}
|
|
}
|
|
print "\n";
|
|
}
|
|
}
|
|
|
|
print "\@end multitable\n";
|
|
}
|
|
|
|
sub print_all {
|
|
my ($i, $max);
|
|
|
|
my ($columns) = 5;
|
|
|
|
# Print only 5 platforms at a time.
|
|
for ($i=0; $i < $#platforms; $i+=$columns) {
|
|
$max = $i+$columns-1 > $#platforms ? $#platforms : $i+$columns-1;
|
|
print_platforms (@platforms[$i .. $max]);
|
|
}
|
|
}
|
|
|
|
sub by_platforms {
|
|
return $pplatforms{$a} cmp $pplatforms{$b};
|
|
}
|