Commit Graph

615 Commits

Author SHA1 Message Date
Rebecca Cran
6bccea7c2b Fix typos - remove duplicate "the".
PR:	bin/154928
Submitted by:	Eitan Adler <lists at eitanadler.com>
MFC after: 	3 days
2011-02-21 09:01:34 +00:00
Murray Stokely
11725f2142 Add complex(3) manual page documenting our partial support for C99
complex arithmetic in libm.

Reviewed by:	David Schultz <das@FreeBSD.org>
MFC after:	2 weeks
2011-02-20 05:29:00 +00:00
David Schultz
b5209b6228 Fix a bug where the wrong argument was passed to SET_FLOAT_WORD().
This bug results in a type mismatch that happens to be harmless
because of the way SET_FLOAT_WORD() works.

Submitted by:	bde
2011-02-10 07:38:38 +00:00
David Schultz
5ffd745ec2 Fix a bug where the wrong argument was passed to INSERT_WORDS().
This bug results in a type mismatch that happens to be harmless
because of the way INSERT_WORDS() works.

Submitted by:	bde
2011-02-10 07:38:13 +00:00
David Schultz
e044d80d08 For small arguments, these functions use simple approximations,
e.g. cos(small) = 1, sin(small) = small.  This commit tightens
the thresholds at which the simple approximations are used.

Reviewed by:	bde
2011-02-10 07:37:50 +00:00
David Schultz
b775d18789 Fix a bogus threshold that was copied from the double precision version.
This commit should have no effect on correctness; it merely changes the
threshold at which a simpler approximation can be used.

Reviewed by:	bde
2011-02-10 07:37:29 +00:00
Konstantin Belousov
9f2e8bdff3 Remove duplicate .note.GNU-stack section declaration.
Reported by:	arundel
2011-02-04 21:54:06 +00:00
Konstantin Belousov
8997563c9a Add section .note.GNU-stack for assembly files used by 386 and amd64. 2011-01-07 16:13:12 +00:00
David Schultz
f353f24867 Another minor nit: Make sure the constant here is a float so the compiler
doesn't promote the entire expression to double.
2010-12-07 03:29:36 +00:00
David Schultz
63687c8b08 Fix various nits in style and comments that were pointed out by bde.
Code changes verified with md5.
2010-12-07 02:19:15 +00:00
David Schultz
177668d11f Add log2() and log2f(). 2010-12-05 22:11:22 +00:00
David Schultz
e7780530fa Add a "kernel" log function, based on e_log.c, which is useful for
implementing accurate logarithms in different bases.  This is based
on an approach bde coded up years ago.

This function should always be inlined; it will be used in only a few
places, and rudimentary tests show a 40% performance improvement in
implementations of log2() and log10() on amd64.

The kernel takes a reduced argument x and returns the same polynomial
approximation as e_log.c, but omitting the low-order term. The low-order
term is much larger than the rest of the approximation, so the caller of
the kernel function can scale it to the appropriate base in extra precision
and obtain a much more accurate answer than by using log(x)/log(b).
2010-12-05 22:11:03 +00:00
David Schultz
9bb4c87bb1 Disable gcc's built-in rint() function when compiling s_nearbyint.c.
It results in incorrect optimizations that break nearbyint().

PR:		143358
Reviewed by:	bde
2010-12-03 00:05:49 +00:00
Ulrich Spörlein
e61ffaea2a Fix bug in jn(3) and jnf(3) that led to -inf results
Explanation by Steve:
jn[f](n,x) for certain ranges of x uses downward recursion to compute
the value of the function.  The recursion sequence that is generated is
proportional to the actual desired value, so a normalization step is
taken.  This normalization is j0[f](x) divided by the zeroth sequence
member.  As Bruce notes, near the zeros of j0[f](x) the computed value
can have giga-ULP inaccuracy. I found for the 1st zero of j0f(x) only
the leading decimal digit is correct.  The solution to the issue is
fairly straight forward.  The zeros of j0(x) and j1(x) never coincide,
so as j0(x) approaches a zero, the normalization constant switches to
j1[f](x) divided by the 2nd sequence member.  The expectation is that
j1[f](x) is a more accurately computed value.

PR:		bin/144306
Submitted by:	Steven G. Kargl <kargl@troutmask.apl.washington.edu>
Reviewed by:	bde
MFC after:	7 days
2010-11-13 10:54:10 +00:00
Dimitry Andric
b3b74eb4e1 Use __FBSDID() instead of RCSID() in most .S files under lib/msun/i386,
and one under lib/msun/amd64.  This avoids adding the identifiers to the
.text section, and moves them to the .comment section instead.

Suggested by:	bde
Approved by:	rpaulo (mentor)
2010-10-01 20:14:36 +00:00
Warner Losh
fca5b4f4d9 This is exactly the same as the .else, so remove it. 2010-09-13 04:23:23 +00:00
Warner Losh
165721e3b1 MFtbemd: Move to using MACHINE_CPUARCH, now that it is safe. 2010-09-13 01:44:56 +00:00
Nathan Whitehorn
b12277d1d4 Repair some build breakage introduced in r211725 and garbage collect some
code made obsolete in the same commit.
2010-08-28 15:03:11 +00:00
Warner Losh
25faff346c MFtbemd:
Prefer MACHNE_CPUARCH to MACHINE_ARCH in most contexts where you want
to test of all the CPUs of a given family conform.
2010-08-23 22:24:11 +00:00
Joel Dahl
c2025a7660 Fix typos, spelling, formatting and mdoc mistakes found by Nobuyuki while
translating these manual pages.  Minor corrections by me.

Submitted by:	Nobuyuki Koganemaru <n-kogane@syd.odn.ne.jp>
2010-08-16 15:18:30 +00:00
Nathan Whitehorn
3c766d1c8f powerpc64 floating-point is identical to powerpc, so use the same
code on both architectures.
2010-07-10 14:40:57 +00:00
David Schultz
efd0f253c2 Introduce __isnanf() as an alias for isnanf(), and make the isnan()
macro expand to __isnanf() instead of isnanf() for float arguments.
This change is needed because isnanf() isn't declared in strict POSIX
or C99 mode.

Compatibility note: Apps using isnan(float) that are compiled after
this change won't link against an older libm.

Reported by:	Florian Forster <octo@verplant.org>
2010-06-12 17:32:05 +00:00
Ulrich Spörlein
df26753b39 mdoc: spell out theta, the Unicode glyph is hard to read for terminal fonts
It is referred to as "theta" later in the document anyway,
so stop being fancy.
2010-06-09 07:31:32 +00:00
Ulrich Spörlein
e3303e900e mdoc: spell macros correctly, there's no need for the backslash escape 2010-06-02 10:20:38 +00:00
Ulrich Spörlein
25c8b07fc2 mdoc: Garbage collect unused/unneeded macros 2010-05-27 13:56:27 +00:00
Ulrich Spörlein
0b31f1f731 mdoc: move remaining sections into consistent order
This pertains mostly to FILES, HISTORY, EXIT STATUS and AUTHORS sections.

Found by:	mdocml lint run
Reviewed by:	ru
2010-05-13 12:08:11 +00:00
Ulrich Spörlein
0afc94c17a mdoc: move CAVEATS, BUGS and SECURITY CONSIDERATIONS sections to the
bottom of the manpages and order them consistently.

GNU groff doesn't care about the ordering, and doesn't even mention
CAVEATS and SECURITY CONSIDERATIONS as common sections and where to put
them.

Found by:	mdocml lint run
Reviewed by:	ru
2010-05-13 12:07:55 +00:00
Ulrich Spörlein
63d46d1d5e Fix several typos in macros or macro misusage.
Found by:	make manlint
Reviewed by:	ru
Approved by:	philip (mentor)
2010-03-12 10:01:06 +00:00
Konstantin Belousov
60d818ef9c Placate new binutils, by using 16-bit %ax instead of 32-bit %eax as an
argument for fnstsw. Explicitely specify sizes for the XMM control and
status word and X87 control and status words.

Reviewed by:	das
Tested by:	avg
MFC after:	2 weeks
2010-02-03 20:23:47 +00:00
Ed Schouten
a4f326ddd5 Use the documented machine constraint for SSE registers.
The amd64-specific bits of msun use an undocumented constraint, which is
less likely to be supported by other compilers (such as Clang). Change
the code to use a more common machine constraint.

Obtained from:	/projects/clangbsd/
2009-06-11 13:59:51 +00:00
Ed Schouten
b492f2899f Use ISO C99 style inline semantics in msun.
Because we use ISO C99 nowadays, we can just get rid of enforcing
GNU89-style inlining.
2009-06-03 08:16:34 +00:00
Attilio Rao
9235ed7199 Use, in uncovered part, the END() macro in order to improve debugging.
In this specific case, Valgrind won't get confused when analyzing such
functions.

Sponsored by:	Sandvine Incorporated
Tested by:	emaste
MFC:		3 days
2009-05-25 14:37:10 +00:00
David Schultz
fbaabc11ae Namespace: scalb() is withdrawn from POSIX. 2009-03-14 18:58:53 +00:00
David Schultz
24863729f9 Eliminate __real__ and __imag__ gccisms. 2009-03-14 18:24:15 +00:00
David Schultz
ea8e257984 C99 TC2 now wants FP_FAST_FMA* to be defined to 1, if the macros are
defined at all. See also: defect report #223.
2009-02-07 05:41:24 +00:00
David Schultz
4630140ce2 Use __gnu89_inline so that these files will compile with newer versions
of gcc, where the meaning of 'inline' was changed to match C99.

Noticed by:	rdivacky
2009-01-13 05:13:20 +00:00
David Schultz
4984f138f8 Fix the types of INFINITY and NAN, which were broken in r131851. They
should both be floats, not doubles.

PR:		127795
Submitted by:	Christoph Mallon
MFC after:	2 weeks
2009-01-08 06:12:03 +00:00
Marcel Moolenaar
74aed9855d Add support for the FPA floating-point format on ARM. The
FPA floating-point format is identical to the VFP format,
but is always stored in big-endian.
Introduce _IEEE_WORD_ORDER to describe the byte-order of
the FP representation.

Obtained from:	Juniper Networks, Inc
2008-12-23 22:20:59 +00:00
David Schultz
941ab616c7 Remove some unused variables.
Reported by:	Intel C Compiler
2008-08-08 00:21:27 +00:00
David Schultz
65faab72b3 In the line
#pragma STDC CX_LIMITED_RANGE   ON
the "ON" needs to be in caps. gcc doesn't understand this pragma
anyway and assumes it is always on in any case, but icc supports
it and cares about the case.
2008-08-08 00:15:16 +00:00
David Schultz
5e9470f1d5 Implement cproj{,f,l}(). 2008-08-07 15:07:48 +00:00
David Schultz
ad5e21e24b Use cpack() and the gcc extension __imag__ to implement cimag() and
conj() instead of using expressions like z * I. The latter is bad for
several reasons:

1. It is implemented using arithmetic, which is unnecessary, and can
   generate floating point exceptions, contrary to the requirements on
   these functions.

2. gcc implements complex multiplication using a formula that breaks
   down for infinities, e.g., it gives INFINITY * I == nan + inf I.
2008-08-07 14:39:56 +00:00
David Schultz
e142bd0ec9 Fix some style bogosity from fdlibm. 2008-08-03 17:49:05 +00:00
David Schultz
e034558322 Minor improvements:
- Improve the order of some tests.
- Fix style.

Submitted by:	bde
2008-08-03 17:39:54 +00:00
David Schultz
9d7d093689 A few minor corrections, including some from bde:
- When y/x is huge, it's faster and more accurate to return pi/2
  instead of pi - pi/2.
- There's no need for 3 lines of bit fiddling to compute -z.
- Fix a comment.
2008-08-02 19:17:00 +00:00
David Schultz
1192a80ed1 On i386, gcc truncates long double constants to double precision
at compile time regardless of the dynamic precision, and there's
no way to disable this misfeature at compile time. Hence, it's
impossible to generate the appropriate tables of constants for the
long double inverse trig functions in a straightforward way on i386;
this change hacks around the problem by encoding the underlying bits
in the table.

Note that these functions won't pass the regression test on i386,
even with the FPU set to extended precision, because the regression
test is similarly damaged by gcc. However, the tests all pass when
compiled with a modified version of gcc.

Reported by:  	bde
2008-08-02 03:56:22 +00:00
David Schultz
8862f666ad Fix some problems with asinf(), acosf(), atanf(), and atan2f():
- Adjust several constants for float precision. Some thresholds
  that were appropriate for double precision were never changed
  when these routines were converted to float precision. This
  has an impact on performance but not accuracy. (Submitted by bde.)

- Reduce the degrees of the polynomials used. A smaller degree
  suffices for float precision.

- In asinf(), use double arithmetic in part of the calculation to
  avoid a corner case and some complicated arithmetic involving a
  division and some buggy constants. This improves performance and
  accuracy.

Max error (ulps):
         asinf  acosf  atanf
before   0.925  0.782  0.852
after    0.743  0.804  0.852

As bde points out, it's cheaper for asin*() and acos*() to use
polynomials instead of rational functions, but that's a task for
another day.
2008-08-01 01:24:25 +00:00
David Schultz
17303c626f Add implementations of acosl(), asinl(), atanl(), atan2l(),
and cargl().

Reviewed by:			bde
sparc64 testing resources from:	remko
2008-07-31 22:41:26 +00:00
David Schultz
d84f6378b9 Set WARNS=1.
I believe I've committed all the bits necessary to make this compile
on all supported architectures. :crosses fingers:
2008-07-31 20:11:37 +00:00
David Schultz
71da0e146b The high part of the mantissa is 64 bits on sparc64. 2008-07-31 20:09:47 +00:00
David Schultz
16608a810d As in other parts of libm, mark a few constants as volatile to prevent
spurious optimizations. gcc doesn't support FENV_ACCESS, so when it
folds constants, it assumes that the rounding mode is always the
default and floating point exceptions never matter.
2008-07-31 19:57:50 +00:00
David Schultz
6684d0ace3 Sort the .PATH entries to give a more reasonable order of precedence:
1. architecture-specific files
     2. long double format-specific files
     3. bsdsrc
     4. src
     5. man
The original order was virtually the opposite of this.

This should not cause any functional changes at this time. The
difference is only significant when one wants to override, say, a
generic foo.c with a more specialized foo.c (as opposed to foo.S).
2008-07-18 02:18:34 +00:00
David Schultz
018b56d61f Fix a typo in the cosl() prototype. 2008-06-28 01:43:24 +00:00
David Schultz
f2dc0faad0 Implement fmodl.
Document fmodl and fix some errors in the fmod manpage.
2008-06-19 22:39:53 +00:00
Oleksandr Tymoshenko
41ea62f986 Symbol.map is handled by cpp, so use C-style comments
Approved by:	cognet (mentor)
2008-05-03 21:16:08 +00:00
Warner Losh
62c97aefc5 Add mips support to libm, from mips2-jnpr perforce branch. 2008-04-26 12:20:29 +00:00
David Schultz
92a1a6e169 Fix some corner cases:
- fma(x, y, z) returns z, not NaN, if z is infinite, x and y are finite,
  x*y overflows, and x*y and z have opposite signs.
- fma(x, y, z) doesn't generate an overflow, underflow, or inexact exception
  if z is NaN or infinite, as per IEEE 754R.
- If the rounding mode is set to FE_DOWNWARD, fma(1.0, 0.0, -0.0) is -0.0,
  not +0.0.
2008-04-03 06:14:51 +00:00
David Schultz
8087c515ab Remove a (bogus) remnant of debugging this on sparc64. 2008-03-31 13:11:45 +00:00
David Schultz
074fb64d9a Add assembly versions of remquol() and remainderl(). 2008-03-30 21:21:53 +00:00
David Schultz
c7392feecc Hook remquol() and remainderl() up to the build. 2008-03-30 20:48:02 +00:00
David Schultz
a2e5f27559 Implement remainderl() as a wrapper around remquol(). The extra work
remquol() performs to compute the quotient is negligible.
2008-03-30 20:47:42 +00:00
David Schultz
cef56f9d6d Implement remquol() based on remquo(). 2008-03-30 20:47:26 +00:00
David Schultz
511dd36b32 Implement csqrtl(). 2008-03-30 20:07:15 +00:00
David Schultz
84c1c0a1ca Hook hypotl() and cabsl() up to the build. 2008-03-30 20:03:46 +00:00
David Schultz
01a13522ad Document hypotl().
Submitted by:	Steve Kargl <sgk@troutmask.apl.washington.edu>
2008-03-30 20:03:29 +00:00
David Schultz
a641fc76eb Alias hypotl() and cabsl() for platforms where long double is the same
as double.
2008-03-30 20:03:06 +00:00
David Schultz
2264157a42 Implement cabsl() in terms of hypotl().
Submitted by:	Steve Kargl <sgk@troutmask.apl.washington.edu>
2008-03-30 20:02:03 +00:00
David Schultz
d23166b015 Implement hypotl(). This is bde's conversion of fdlibm hypot(), with minor
fixes for ld128 by me.
2008-03-30 20:01:50 +00:00
Bruce Evans
42ee187c3c Use fabs[f]() instead of bit fiddling for setting absolute values.
This makes little difference in float precision, but in double
precision gives a speedup of about 30% on amd64 (A64 CPU) and i386
(A64).  This depends on fabs[f]() being inline and efficient.  The
bit fiddling (or any use of SET_HIGH_WORD(), which libm does too
much because it was best on old 32-bit machines) always causes
packing overheads and sometimes causes stalls in the packing, since
it operates on only part of a variable in the double precision case.
It apparently did cause stalls in a critical path here.
2008-03-30 18:07:12 +00:00
Bruce Evans
c0c7ddd3a8 Use the expression fabs(x+0.0)-fabs(y+0.0) instead of
fabs(x+0.0)+fabs(y+0.0) when mixing NaNs.  This improves
consistency of the result by making it harder for the compiler to reorder
the operands.  (FP addition is not necessarily commutative because the
order of operands makes a difference on some machines iff the operands are
both NaNs.)
2008-03-30 17:28:27 +00:00
Bruce Evans
f94997c8d7 Fix a missing mask in a hi+lo decomposition. Thus bug made the extra
precision in software useless, so hypotf() had some errors in the 1-2
ulp range unless there is extra precision in hardware (as happens on
i386).
2008-03-30 17:17:42 +00:00
David Schultz
a1af0d70da Include math.h for the fmaf() prototype. 2008-03-29 16:38:29 +00:00
David Schultz
ee0730e61e Fix some rather obscene code that has ambiguous if...if...else...
constructs in it.
2008-03-29 16:37:59 +00:00
David Schultz
3e13dd37ff 1 << 47 needs to be written 1ULL << 47. 2008-03-02 20:16:55 +00:00
David Schultz
e43c8f6acc Hook up sqrtl() to the build. 2008-03-02 01:48:17 +00:00
David Schultz
c6f56f9f41 MD implementations of sqrtl(). 2008-03-02 01:48:08 +00:00
David Schultz
c6a4447b64 MI implementation of sqrtl(). This is very slow and should
be overridden when hardware sqrt is available.
2008-03-02 01:47:58 +00:00
Bruce Evans
a278d99026 Fix and improve some magic numbers for the "medium size" case.
e_rem_pio2.c:
This case goes up to about 2**20pi/2, but the comment about it said that
it goes up to about 2**19pi/2.

It went too far above 2**pi/2, giving a multiplier fn with 21 significant
bits in some cases.  This would be harmful except for a numerical
accident.  It happens that the terms of the approximation to pi/2,
when rounded to 33 bits so that multiplications by 20-bit fn's are
exact, happen to be rounded to 32 bits so multiplications by 21-bit
fn's are exact too, so the bug only complicates the error analysis (we
might lose a bit of accuracy but have bits to spare).

e_rem_pio2f.c:
The bogus comment in e_rem_pio2.c was copied and the code was changed
to be bug-for-bug compatible with it, except the limit was made 90
ulps smaller than necessary.  The approximation to pi/2 was not
modified except for discarding some of it.

The same rough error analysis that justifies the limit of 2**20pi/2
for double precision only justifies a limit of 2**18pi/2 for float
precision.  We depended on exhaustive testing to check the magic numbers
for float precision.  More exaustive testing shows that we can go up
to 2**28pi/2 using a 53+25 bit approximation to pi/2 for float precision,
with a the maximum error for cosf() and sinf() unchanged at 0.5009
ulps despite the maximum error in rem_pio2f being ~0.25 ulps.  Implement
this.
2008-02-28 16:22:36 +00:00
Bruce Evans
e822ea5b2a Inline __ieee754__rem_pio2f(). On amd64 (A64) and i386 (A64), this
gives an average speedup of about 12 cycles or 17% for
9pi/4 < |x| <= 2**19pi/2 and a smaller speedup for larger x, and a
small speeddown for |x| <= 9pi/4 (only 1-2 cycles average, but that
is 4%).

Inlining this is less likely to bust caches than inlining the float
version since it is much smaller (about 220 bytes text and rodata) and
has many fewer branches.  However, the float version was already large
due to its manual inlining of the branches and also the polynomial
evaluations.
2008-02-25 22:19:17 +00:00
Bruce Evans
c32951b16e Use a temporary array instead of the arg array y[] for calling
__kernel_rem_pio2().  This simplifies analysis of aliasing and thus
results in better code for the usual case where __kernel_rem_pio2()
is not called.  In particular, when __ieee854_rem_pio2[f]() is inlined,
it normally results in y[] being returned in registers.  I couldn't
get this to work using the restrict qualifier.

In float precision, this saves 2-3% in most cases on amd64 and i386
(A64) despite it not being inlined in float precision yet.  In double
precision, this has high variance, with an average gain of 2% for
amd64 and 0.7% for i386 (but a much larger gain for usual cases) and
some losses.
2008-02-25 18:28:58 +00:00
Bruce Evans
70d818a20e Change __ieee754_rem_pio2f() to return double instead of float so that
this function and its callers cosf(), sinf() and tanf() don't waste time
converting values from doubles to floats and back for |x| > 9pi/4.
All these functions were optimized a few years ago to mostly use doubles
internally and across the __kernel*() interfaces but not across the
__ieee754_rem_pio2f() interface.

This saves about 40 cycles in cosf(), sinf() and tanf() for |x| > 9pi/4
on amd64 (A64), and about 20 cycles on i386 (A64) (except for cosf()
and sinf() in the upper range).  40 cycles is about 35% for |x| < 9pi/4
<= 2**19pi/2 and about 5% for |x| > 2**19pi/2.  The saving is much
larger on amd64 than on i386 since the conversions are not easy to
optimize except on i386 where some of them are automatic and others
are optimized invalidly.  amd64 is still about 10% slower in cosf()
and tanf() in the lower range due to conversion overhead.

This also gives a tiny speedup for |x| <= 9pi/4 on amd64 (by simplifying
the code).  It also avoids compiler bugs and/or additional slowness
in the conversions on (not yet supported) machines where double_t !=
double.
2008-02-25 13:33:20 +00:00
Bruce Evans
0d1564b6c7 Fix some off-by-1 errors.
e_rem_pio2.c:
Float and double precision didn't work because init_jk[] was 1 too small.
It needs to be 2 larger than you might expect, and 1 larger than it was
for these precisions, since its test for recomputing needs a margin of
47 bits (almost 2 24-bit units).

init_jk[] seems to be barely enough for extended and quad precisions.
This hasn't been completely verified.  Callers now get about 24 bits
of extra precision for float, and about 19 for double, but only about
8 for extended and quad.  8 is not enough for callers that want to
produce extra-precision results, but current callers have rounding
errors of at least 0.8 ulps, so another 1/2**8 ulps of error from the
reduction won't affect them much.

Add a comment about some of the magic for init_jk[].

e_rem_pio2.c:
Double precision worked in practice because of a compensating off-by-1
error here.  Extended precision was asked for, and it executed exactly
the same code as the unbroken double precision.

e_rem_pio2f.c:
Float precision worked in practice because of a compensating off-by-1
error here.  Double precision was asked for, and was almost needed,
since the cosf() and sinf() callers want to produce extra-precision
results, at least internally so that their error is only 0.5009 ulps.
However, the extra precision provided by unbroken float precision is
enough, and the double-precision code has extra overheads, so the
off-by-1 error cost about 5% in efficiency on amd64 and i386.
2008-02-25 11:43:20 +00:00
Rafal Jaworowski
56ae1bed48 Let PowerPC world optionally build with -msoft-float. For FPU-less PowerPC
variations (e500 currently), this provides a gcc-level FPU emulation and is an
alternative approach to the recently introduced kernel-level emulation
(FPU_EMU).

Approved by:	cognet (mentor)
MFp4:		e500
2008-02-24 19:22:53 +00:00
Bruce Evans
60a50c2585 Optimize the 9pi/2 < |x| <= 2**19pi/2 case some more by avoiding an
fabs(), a conditional branch, and sign adjustments of 3 variables for
x < 0 when the branch is taken.  In double precision, even when the
branch is perfectly predicted, this saves about 10 cycles or 10% on
amd64 (A64) and i386 (A64) for the negative half of the range, but
makes little difference for the positive half of the range.  In float
precision, it also saves about 4 cycles for the positive half of the
range on i386, and many more cycles in both halves on amd64 (28 in the
negative half and 11 in the positive half for tanf), but the amd64
times for float precision are anomalously slow so the larger
improvement is only a side effect.

Previous commits arranged for the x < 0 case to be handled simply:
- one part of the rounding method uses the magic number 0x1.8p52
  instead of the usual 0x1.0p52.  The latter is required for large |x|,
  but it doesn't work for negative x and we don't need it for large |x|.
- another part of the rounding method no longer needs to add `half'.
  It would have needed to add -half for negative x.
- removing the "quick check no cancellation" in the double precision
  case removed the need to take the absolute value of the quadrant
  number.

Add my noncopyright in e_rem_pio2.c
2008-02-23 12:53:21 +00:00
Bruce Evans
dbf10e45c4 Avoid using FP-to-integer conversion for !(amd64 || i386) too. Use the
FP-to-FP method to round to an integer on all arches, and convert this
to an int using FP-to-integer conversion iff irint() is not available.
This is cleaner and works well on at least ia64, where it saves 20-30
cycles or about 10% on average for 9Pi/4 < |x| <= 32pi/2 (should be
similar up to 2**19pi/2, but I only tested the smaller range).

After the previous commit to e_rem_pio2.c removed the "quick check no
cancellation" non-optimization, the result of the FP-to-integer
conversion is not needed so early, so using irint() became a much
smaller optimization than when it was committed.

An earlier commit message said that cos, cosf, sin and sinf were equally
fast on amd64 and i386 except for cos and sin on i386.  Actually, cos
and sin on amd64 are equally fast to cosf and sinf on i386 (~88 cycles),
while cosf and sinf on amd64 are not quite equally slow to cos and sin
on i386 (average 115 cycles with more variance).
2008-02-22 18:43:23 +00:00
Bruce Evans
7c1b5e7953 Remove the "quick check no cancellation" optimization for
9pi/2 < |x| < 32pi/2 since it is only a small or negative optimation
and it gets in the way of further optimizations.  It did one more
branch to avoid some integer operations and to use a different
dependency on previous results.  The branches are fairly predictable
so they are usually not a problem, so whether this is a good
optimization depends mainly on the timing for the previous results,
which is very machine-dependent.  On amd64 (A64), this "optimization"
is a pessimization of about 1 cycle or 1%; on ia64, it is an
optimization of about 2 cycles or 1%; on i386 (A64), it is an
optimization of about 5 cycles or 4%; on i386 (Celeron P2) it is an
optimization of about 4 cycles or 3% for cos but a pessimization of
about 5 cycles for sin and 1 cycle for tan.  I think the new i386
(A64) slowness is due to an pipeline stall due to an avoidable
load-store mismatch (so the old timing was better), and the i386
(Celeron) variance is due to its branch predictor not being too good.
2008-02-22 17:26:24 +00:00
Bruce Evans
43590b1517 Optimize the 9pi/2 < |x| <= 2**19pi/2 case on amd64 and i386 by avoiding
the the double to int conversion operation which is very slow on these
arches.  Assume that the current rounding mode is the default of
round-to-nearest and use rounding operations in this mode instead of
faking this mode using the round-towards-zero mode for conversion to
int.  Round the double to an integer as a double first and as an int
second since the double result is needed much earler.

Double rounding isn't a problem since we only need a rough approximation.
We didn't support other current rounding modes and produce much larger
errors than before if called in a non-default mode.

This saves an average about 10 cycles on amd64 (A64) and about 25 on
i386 (A64) for x in the above range.  In some cases the saving is over
25%.  Most cases with |x| < 1000pi now take about 88 cycles for cos
and sin (with certain CFLAGS, etc.), except on i386 where cos and sin
(but not cosf and sinf) are much slower at 111 and 121 cycles respectivly
due to the compiler only optimizing well for float precision.  A64
hardware cos and sin are slower at 105 cycles on i386 and 110 cycles
on amd64.
2008-02-22 15:55:14 +00:00
Bruce Evans
0ddfa46b44 Add an irint() function in inline asm for amd64 and i386. irint() is
the same as lrint() except it returns int instead of long.  Though the
extern lrint() is fairly fast on these arches, it still takes about
12 cycles longer than the inline version, and 12 cycles is a lot in
applications where [li]rint() is used to avoid slow conversions that
are only a couple of times slower.

This is only for internal use.  The libm versions of *rint*() should
also be inline, but that would take would take more header engineering.
Implementing irint() instead of lrint() also avoids a conflict with
the extern declaration of the latter.
2008-02-22 14:11:03 +00:00
Bruce Evans
f839bac29c Optimize the conversion to bits a little (by about 11 cycles or 16%
on i386 (A64), 5 cycles on amd64 (A64), and 3 cycles on ia64).  gcc
tends to generate very bad code for accessing floating point values
as bits except when the integer accesses have the same width as the
floating point values, and direct accesses to bit-fields (as is common
only for long double precision) always gives such accesses.  Use the
expsign access method, which is good for 80-bit long doubles and
hopefully no worse for 128-bit long doubles.  Now the generated code
is less bad.  There is still unnecessary copying of the arg on amd64
and i386 and mysterious extra slowness on amd64.
2008-02-22 11:59:05 +00:00
Bruce Evans
a7aa8cc980 Optimize the fixup for +-0 by using better classification for this case
and by using a table lookup to avoid a branch when this case occurs.
On i386, this saves 1-4 cycles out of about 64 for non-large args.
2008-02-22 10:04:53 +00:00
Bruce Evans
33843eef65 Fix rintl() on signaling NaNs and unsupported formats. 2008-02-22 09:21:14 +00:00
David Schultz
5aa554c7e5 s/rcsid/__FBSDID/ 2008-02-22 02:30:36 +00:00
David Schultz
fab324dfa4 Remove an unused variable. 2008-02-22 02:27:34 +00:00
David Schultz
7cd50f4d94 Eliminate some warnings. 2008-02-22 02:26:51 +00:00
Bruce Evans
f21d26becb Merge cosmetic changes from e_rem_pio2.c 1.10 (convert to __FBSDID();
fix indentation and return type of __ieee754_rem_pio2()).

Remove unused variables.
2008-02-19 15:42:46 +00:00
Bruce Evans
9e9d3bc9f1 Optimize for 3pi/4 <= |x| <= 9pi/4 in much the same way as for
pi/4 <= |x| <= 3pi/4.  Use the same branch ladder as for float precision.
Remove the optimization for |x| near pi/2 and don't do it near the
multiples of pi/2 in the newly optimized range, since it requires
fairly large code to handle only relativley few cases.  Ifdef out
optimization for |x| <= pi/4 since this case can't occur because it
is done in callers.

On amd64 (A64), for cos() and sin() with uniformly distributed args,
no cache misses, some parallelism in the caller, and good but not great
CC and CFLAGS, etc., this saves about 40 cycles or 38% in the newly
optimized range, or about 27% on average across the range |x| <= 2pi
(~65 cycles for most args, while the A64 hardware fcos and fsin take
~75 cycles for half the args and 125 cycles for the other half).  The
speedup for tan() is much smaller, especially relatively.  The speedup
on i386 (A64) is slightly smaller, especially relatively.  i386 is
still much slower than amd64 here (unlike in the float case where it
is slightly faster).
2008-02-19 15:30:58 +00:00
Bruce Evans
9ce8756044 Rearrange the polynomial evaluation for better parallelism. This
saves an average of about 8 cycles or 5% on A64 (amd64 and i386 --
more in cycles but about the same percentage on i386, and more with
old versions of gcc) with good CFLAGS and some parallelism in the
caller.  As usual, it takes a couple more multiplications so it will
be slower on old machines.

Convert to __FBSDID().
2008-02-19 12:54:14 +00:00
David Schultz
345241c5e0 Document return values better. 2008-02-18 19:02:49 +00:00
David Schultz
71c11dd528 Add tgammaf() as a simple wrapper around tgamma(). 2008-02-18 17:27:11 +00:00
Bruce Evans
be396b71c1 2 long double constants were missing L suffixes. This helped break tanl()
on !(amd64 || i386).  It gave slightly worse than double precision in some
cases.  tanl() now passes tests of 2^24 values on ia64.
2008-02-18 15:39:52 +00:00