Commit Graph

539 Commits

Author SHA1 Message Date
bde
d32d47f4d6 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
bde
f77d7dfd70 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
bde
49cb35343e 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
bde
83268c5f08 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
bde
ce9e405fdb 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
raj
69575dab52 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
bde
09a79b45a1 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
bde
26ba55ab66 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
bde
e31bf4b688 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
bde
37c23ae5ff 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
bde
af1dfd5050 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
bde
d3a4e4141f 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
bde
95a5ac1745 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
bde
dc8c48731a Fix rintl() on signaling NaNs and unsupported formats. 2008-02-22 09:21:14 +00:00
das
8b6c2ddfd4 s/rcsid/__FBSDID/ 2008-02-22 02:30:36 +00:00
das
224826f963 Remove an unused variable. 2008-02-22 02:27:34 +00:00
das
d74b55ed2b Eliminate some warnings. 2008-02-22 02:26:51 +00:00
bde
f0e3007ba6 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
bde
30565c600e 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
bde
e508bf1279 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
das
0a944b08e4 Document return values better. 2008-02-18 19:02:49 +00:00
das
11fca9d5f5 Add tgammaf() as a simple wrapper around tgamma(). 2008-02-18 17:27:11 +00:00
bde
3a3915219d 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
bde
3fc58437c4 Fix a typo which broke k_tanl.c on !(amd64 || i386). 2008-02-18 14:09:41 +00:00
bde
ad78d66621 Inline __ieee754__rem_pio2(). With gcc4-2, this gives an average
optimization of about 10% for cos(x), sin(x) and tan(x) on
|x| < 2**19*pi/2.  We didn't do this before because __ieee754__rem_pio2()
is too large and complicated for gcc-3.3 to inline very well.  We don't
do this for float precision because it interferes with optimization
of the usual (?) case (|x| < 9pi/4) which is manually inlined for float
precision only.

This has some rough edges:
- some static data is duplicated unnecessarily.  There isn't much after
  the recent move of large tables to k_rem_pio2.c, and some static data
  is duplicated to good affect (all the data static const, so that the
  compiler can evaluate expressions like 2*pio2 at compile time and
  generate even more static data for the constant for this).
- extern inline is used (for the same reason as in previous inlining of
  k_cosf.c etc.), but C99 apparently doesn't allow extern inline
  functions with static data, and gcc will eventually warn about this.

Convert to __FBSDID().

Indent __ieee754_rem_pio2()'s declaration consistently (its style was
made inconsistent with fdlibm a while ago, so complete this).

Fix __ieee754_rem_pio2()'s return type to match its prototype.  Someone
changed too many ints to int32_t's when fixing the assumption that all
ints are int32_t's.
2008-02-18 14:02:12 +00:00
das
2acea74331 Use volatile hacks to make sure exp() generates an underflow
exception when it's supposed to. Previously, gcc -O2 was optimizing
away the statement that generated it.
2008-02-17 21:53:19 +00:00
das
10502fe2a1 Hook up sinl(), cosl(), and tanl() to the build. 2008-02-17 07:33:51 +00:00
das
42e85f679f Add implementations of sinl(), cosl(), and tanl().
Submitted by:	Steve Kargl <sgk@apl.washington.edu>
2008-02-17 07:33:12 +00:00
das
61222ca5ae Documentation for sinl(), cosl(), and tanl(). 2008-02-17 07:32:44 +00:00
das
11a058bb6d Add kernel functions for 128-bit long doubles. These could be improved
a bit, but access to a freebsd/sparc64 machine is needed.

Submitted by:	bde and Steve Kargl <sgk@apl.washington.edu> (earlier version)
2008-02-17 07:32:31 +00:00
das
91ec53b876 Add kernel functions for 80-bit long doubles. Many thanks to Steve and
Bruce for putting lots of effort into these; getting them right isn't
easy, and they went through many iterations.

Submitted by:	Steve Kargl <sgk@apl.washington.edu> with revisions from bde
2008-02-17 07:32:14 +00:00
das
832e12bedd Add more pi for long doubles. Also, avoid storing multiple copies
of the pi/2 array, as it is unlikely to vary, except in Indiana.
2008-02-17 07:31:59 +00:00
bde
febd0ab45e Sigh, the weak reference for ceill(), floorl() and truncl() was in
unreachable code due to a missing include.  This kept arm and powerpc
broken.

Reported by:	sam, grehan
2008-02-15 07:01:40 +00:00
bde
d3836a4dd2 Oops, the weak reference for ceill(), floorl() and truncl() was in the
wrong file.  This broke arm and powerpc.

Reported by:	grehan
2008-02-14 15:10:34 +00:00
bde
fda3d327bb Use the expression fabs(x+0.0)+fabs(y+0.0) instad of a+b (where a is
|x| or |y| and b is |y| or |x|) when mixing NaN arg(s).

hypot*() had its own foot shooting for mixing NaNs -- it swaps the
args so that |x| in bits is largest, but does this before quieting
signaling NaNs, so on amd64 (where the result of adding NaNs depends
on the order) it gets inconsistent results if setting the quiet bit
makes a difference, just like a similar ia64 and i387 hardware comparison.
The usual fix (see e_powf.c 1.13 for more details) of mixing using
(a+0.0)+-(b+0.0) doesn't work on amd64 if the args are swapped (since
the rder makes a difference with SSE). Fortunately, the original args
are unchanged and don't need to be swapped when we let the hardware
decide the mixing after quieting them, but we need to take their
absolute value.

hypotf() doesn't seem to have any real bugs masked by this non-bug.
On amd64, its maximum error in 2^32 trials on amd64 is now 0.8422 ulps,
and on i386 the maximum error is unchanged and about the same, except
with certain CFLAGS it magically drops to 0.5 (perfect rounding).

Convert to __FBSDID().
2008-02-14 13:44:03 +00:00
bde
30aa45f24b Fix the hi+lo decomposition for 2/(3ln2). The decomposition needs to
be into 12+24 bits of precision for extra-precision multiplication,
but was into 13+24 bits.  On i386 with -O1 the bug was hidden by
accidental extra precision, but on amd64, in 2^32 trials the bug
caused about 200000 errors of more than 1 ulp, with a maximum error
of about 80 ulps.  Now the maximum error in 2^32 trials on amd64
is 0.8573 ulps.  It is still 0.8316 ulps on i386 with -O1.

The nearby decomposition of 1/ln2 and the decomposition of 2/(3ln2) in
the double precision version seem to be sub-optimal but not broken.
2008-02-14 10:23:51 +00:00
bde
dba8069abd Use the expression (x+0.0)-(y+0.0) instead of x+y when mixing NaN arg(s).
This uses 2 tricks to improve consistency so that more serious problems
aren't hidden in simple regression tests by noise for the NaNs:

- for a signaling NaN, adding 0.0 generates the invalid exception and
  converts to a quiet NaN, and doesn't have too many effects for other
  types of args (it converts -0 to +0 in some rounding modes, but that
  hopefully doesn't change the result after adding the NaN arg).  This
  avoids some inconsistencies on i386 and ia64.  On these arches, the
  result of an operation on 2 NaNs is apparently the largest or the
  smallest of the NaNs as bits (consistently largest or smallest for
  each arch, but the opposite).  I forget which way the comparison
  goes and if the sign bit affects it.  The quiet bit is is handled
  poorly by not always setting it before the comparision or ignoring
  it.  Thus if one of the args was originally a signaling NaN and the
  other was originally a quiet NaN, then the result depends too much
  on whether the signaling NaN has been quieted at this point, which
  in turn depends on optimizations and promotions.  E.g., passing float
  signaling NaNs to double functions must quiet them on conversion;
  on i387, loading a signaling NaN of type float or double (but not
  long double) into a register involves a conversion, so it quiets
  signaling NaNs, so if the addition has 2 register operands than it
  only sees quiet NaNs, but if the addition has a memory operand then
  it sees a signaling NaN iff it is in the memory operand.

- subtraction instead of addition is used to avoid a dubious optimization
  in old versions of gcc.  For SSE operations, mixing of NaNs apparently
  always gives the target operand.  This is not as good as the i387
  and ia64 behaviour.  It doesn't mix NaNs at all, and makes addition
  not quite commutative.  Old versions of gcc sometimes rewrite x+y
  to y+x and thus give different results (in bits) for NaNs.  gcc-3.3.3
  rewrites x+y to y+x for one of pow() and powf() but not the other,
  so starting from float NaN args x and y, powf(x, y) was almost always
  different from pow(x, y).

These tricks won't give consistency of 2-arg float and double functions
with long double ones on amd64, since long double ones use the i387
which has different semantics from SSE.

Convert to __FBSDID().
2008-02-14 09:42:24 +00:00
bde
5f2db8f916 s_ceill.c
s_floorl.c
s_truncl.c
2008-02-13 17:38:16 +00:00
bde
234b4ba1f7 On arches where long double is the same as double, alias ceil(), floor()
and trunc() to the corresponding long double functions.  This is not
just an optimization for these arches.  The full long double functions
have a wrong value for `huge', and the arches without full long doubles
depended on it being wrong.
2008-02-13 16:56:52 +00:00
bde
403416b247 Fix the C version of ceill(x) for -1 < x <= -0 in all rounding modes.
The result should be -0, but was +0.
2008-02-13 15:22:53 +00:00
bde
517ddcfb70 Fix exp2*(x) on signaling NaNs by returning x+x as usual.
This has the side effect of confusing gcc-4.2.1's optimizer into more
often doing the right thing.  When it does the wrong thing here, it
seems to be mainly making too many copies of x with dependency chains.
This effect is tiny on amd64, but in some cases on i386 it is enormous.
E.g., on i386 (A64) with -O1, the current version of exp2() should
take about 50 cycles, but took 83 cycles before this change and 66
cycles after this change.  exp2f() with -O1 only speeded up from 51
to 47 cycles.  (exp2f() should take about 40 cycles, on an Athlon in
either i386 or amd64 mode, and now takes 42 on amd64).  exp2l() with
-O1 slowed down from 155 cycles to 123 for some args; this is unimportant
since the i386 exp2l() is a fake; the wrong thing for it seems to
involve branch misprediction.
2008-02-13 10:44:44 +00:00
bde
d2c1b707cd Rearrange the polynomial evaluation for better parallelism. This is
faster on all machines tested (old Celeron (P2), A64 (amd64 and i386)
and ia64) except on ia64 when compiled with -O1.  It takes 2 more
multiplications, so it will be slower on old machines.  The speedup
is about 8 cycles = 17% on A64 (amd64 and i386) with best CFLAGS
and some parallelism in the caller.

Move the evaluation of 2**k up a bit so that it doesn't compete too
much with the new polynomial evaluation.  Unlike the previous
optimization, this rearrangement cannot change the result, so compilers
and CPU schedulers can do it, but they don't do it quite right yet.
This saves a whole 1 or 2 cycles on A64.
2008-02-13 08:36:13 +00:00
bde
85c145264c Use hardware remainder on amd64 since it is 5 to 10 times faster than
software remainder and is already used for remquo().
2008-02-13 06:01:48 +00:00
bde
d22d4d7357 Fix remainder() and remainderf() in round-towards-minus-infinity mode
when the result is +-0.  IEEE754 requires (in all rounding modes) that
if the result is +-0 then its sign is the same as that of the first
arg, but in round-towards-minus-infinity mode an uncorrected implementation
detail always reversed the sign.  (The detail is that x-x with x's
sign positive gives -0 in this mode only, but the algorithm assumed
that x-x always has positive sign for such x.)

remquo() and remquof() seem to need the same fix, but I cannot test them
yet.

Use long doubles when mixing NaN args.  This trick improves consistency
of results on at least amd64, so that more serious problems like the
above aren't hidden in simple regression tests by noise for the NaNs.
On amd64, hardware remainder should be used since it is about 10 times
faster than software remainder and is already used for remquo(), but
it involves using the i387 even for floats and doubles, and the i387
does NaN mixing which is better than but inconsistent with SSE NaN mixing.
Software remainder() would probably have been inconsistent with
software remainderl() for the same reason if the latter existed.

Signaling NaNs cause further inconsistencies on at least ia64 and i386.

Use __FBSDID().
2008-02-12 17:11:36 +00:00
bde
a75ea6c233 Use double precision for z and thus for the entire calculation of
exp2(i/TBLSIZE) * p(z) instead of only for the final multiplication
and addition.  This fixes the code to match the comment that the maximum
error is 0.5010 ulps (except on machines that evaluate float expressions
in extra precision, e.g., i386's, where the evaluation was already
in extra precision).

Fix and expand the comment about use of double precision.

The relative roundoff error from evaluating p(z) in non-extra precision
was about 16 times larger than in exp2() because the interval length
is 16 times smaller.  Its maximum was at least P1 * (1.0 ulps) *
max(|z|) ~= log(2) * 1.0 * 1/32 ~= 0.0217 ulps (1.0 ulps from the
addition in (1 + P1*z) with a cancelation error when z ~= -1/32).  The
actual final maximum was 0.5313 ulps, of which 0.0303 ulps must have
come from the additional roundoff error in p(z).  I can't explain why
the additional roundoff error was almost 3/2 times larger than the rough
estimate.
2008-02-11 05:20:02 +00:00
bde
1960b378b5 As usual, use a minimax polynomial that is specialized for float
precision.  The new polynomial has degree 4 instead of 10, and a maximum
error of 2**-30.04 ulps instead of 2**-33.15.  This doesn't affect the
final error significantly; the maximum error was and is about 0.5015
ulps on i386 -O1, and the number of cases with an error of > 0.5 ulps
is increased from 13851 to 14407.

Note that the error is only this close to 0.5 ulps due to excessive
extra precision caused by compiler bugs on i386.  The extra precision
could be obtained intentionally, and is useful for keeping the error
of the hyperbolic float functions below 1 ulp, since these functions
are implemented using expm1f.  My recent change for scaling by 2**k
had the unintentional side effect of retaining extra precision for
longer, so callers of expm1f see errors of more like 0.0015 ulps than
0.5015 ulps, and for the hyperbolic functions this reduces the maximum
error from nearly about 2 ulps to about 0.75 ulps.

This is about 10% faster on i386 (A64).  expm1* is still very slow,
but now the float version is actually significantly faster.  The
algorithm is very sophisticated but not very good except on machines
with fast division.
2008-02-09 12:53:15 +00:00
bde
d28692763b Fix a comment about coefficients and expand a related one. 2008-02-09 10:36:07 +00:00
bde
4fa28da3c9 Fix truncl() when the result should be -0.0L. When the result is +-0.0L,
it must have the same sign as the arg in all rounding modes, but it was
always +0.0L.
2008-02-08 01:45:52 +00:00
bde
ef3758c4ac Oops, fix the fix in rev.1.10. logb() and logbf() were broken on
denormals, and logb() remained broken after 1.10 because the fix for
logbf() was incompletely translated.

Convert to __FBSDID().
2008-02-08 01:22:13 +00:00
bde
efcf10f47b Use a better method of scaling by 2**k. Instead of adding to the
exponent bits of the reduced result, construct 2**k (hopefully in
parallel with the construction of the reduced result) and multiply by
it.  This tends to be much faster if the construction of 2**k is
actually in parallel, and might be faster even with no parallelism
since adjustment of the exponent requires a read-modify-wrtite at an
unfortunate time for pipelines.

In some cases involving exp2* on amd64 (A64), this change saves about
40 cycles or 30%.  I think it is inherently only about 12 cycles faster
in these cases and the rest of the speedup is from partly-accidentally
avoiding compiler pessimizations (the construction of 2**k is now
manually scheduled for good results, and -O2 doesn't always mess this
up).  In most cases on amd64 (A64) and i386 (A64) the speedup is about
20 cycles.  The worst case that I found is expf on ia64 where this
change is a pessimization of about 10 cycles or 5%.  The manual
scheduling for plain exp[f] is harder and not as tuned.

Details specific to expm1*:
- the saving is closer to 12 cycles than to 40 for expm1* on i386 (A64).
  For some reason it is much larger for negative args.
- also convert to __FBSDID().
2008-02-07 09:42:19 +00:00
bde
22e608f1ce Use a better method of scaling by 2**k. Instead of adding to the
exponent bits of the reduced result, construct 2**k (hopefully in
parallel with the construction of the reduced result) and multiply by
it.  This tends to be much faster if the construction of 2**k is
actually in parallel, and might be faster even with no parallelism
since adjustment of the exponent requires a read-modify-wrtite at an
unfortunate time for pipelines.

In some cases involving exp2* on amd64 (A64), this change saves about
40 cycles or 30%.  I think it is inherently only about 12 cycles faster
in these cases and the rest of the speedup is from partly-accidentally
avoiding compiler pessimizations (the construction of 2**k is now
manually scheduled for good results, and -O2 doesn't always mess this
up).  In most cases on amd64 (A64) and i386 (A64) the speedup is about
20 cycles.  The worst case that I found is expf on ia64 where this
change is a pessimization of about 10 cycles or 5%.  The manual
scheduling for plain exp[f] is harder and not as tuned.

This change ld128/s_exp2l.c has not been tested.
2008-02-07 03:17:05 +00:00
bde
bd06cb56ab As for the float trig functions and logf, use a minimax polynomial
that is specialized for float precision.  The new polynomial has degree
5 instead of 11, and a maximum error of 2**-27.74 ulps instead
of 2**-30.64.  This doesn't affect the final error significantly; the
maximum error was and is about 0.9101 ulps on amd64 -01 and the number
of cases with an error of > 0.5 ulps is actually reduced by epsilon
despite the larger error in the polynomial.

This is about 15% faster on amd64 (A64), i386 (A64) and ia64.  The asm
version is still used instead of this on i386 since it is faster and
more accurate.
2008-02-06 06:35:21 +00:00
das
b2c068251b Adjust the exponent before converting the result from double to
float precision. This fixes some double rounding problems for
subnormals and simplifies things a bit.
2008-01-28 01:19:07 +00:00
bde
997d2d26fb Fix a harmless type error in 1.9. 2008-01-25 21:09:21 +00:00
bde
babf3acb0e Fix cutoffs. This is just a cleanup and an optimization for unusual
cases which are used mainly by regression tests.

As usual, the cutoff for tiny args was not correctly translated to
float precision.  It was 2**-54 but 2**-24 works.  It must be about
2**-precision, since the error from approximating log(1+x) by x is
about the same as |x|.  Exhaustive testing shows that 2**-24 gives
perfect rounding in round-to-nearest mode.

Similarly for the cutoff for being small, except this is not used by
so many other functions.  It was 2**-29 but 2**-15 works.  It must be
a bit smaller than sqrt(2**-precision), since the error from
approximating log(1+x) by x-x*x/2 is about the same as x*x.  Exhaustive
testing shows that 2**-15 gives a maximum error of 0.5052 ulps in
round-to-nearest-mode.  The algorithm for the general case is only good
for 0.8388 ulps, so this is sufficient (but it loses slightly on i386 --
then extra precision gives 0.5032 ulps for the general case).

While investigating this, I noticed that optimizing the usual case by
falling into a middle case involving a simple polynomial evaluation
(return x-x*x/2 instead of x here) is not such a good idea since it
gives an enormous pessimization of tinier args on machines for which
denormals are slow.  Float x*x/2 is denormal when |x| ~< 2**-64 and
x*x/2 is evaluated in float precision, so it can easily be denormal
for normal x.  This is even more interesting for general polynomial
evaluations.  Multiplying out large powers of x is normally a good
optimization since it reduces dependencies, but it creates denormals
starting with quite large x.
2008-01-21 13:46:21 +00:00
bde
ef5ed15ee4 Oops, when merging from the float version to the double versions, don't
forget to translate "float" to "double".

ucbtest didn't detect the bug, but exhaustive testing of the float
case relative to the double case eventually did.  The bug only affects
args x with |x| ~> 2**19*(pi/2) on non-i386 (i386 is broken in a
different way for large args).
2008-01-20 04:09:44 +00:00
bde
b3048e4365 Remove the float version of the kernel of arg reduction for pi/2, since
it should never have existed and it has not been used for many years
(floats are reduced faster using doubles).  All relevant changes (just
the workaround for broken assignment) have been merged to the double
version.
2008-01-19 22:50:50 +00:00
bde
2005bbb395 Do an ordinary assignment in STRICT_ASSIGN() except for floats until
there is a problem with non-floats (when i386 defaults to extra
precision).  This essentially restores yesterday's behaviour for doubles
on i386 (since generic rint() isn't used and everywhere else assumed
working assignment), but for arches that use the generic rint() it
finishes restoring some of 1995's behaviour (don't waste time doing
unnecessary store/load).
2008-01-19 22:05:14 +00:00
bde
8499893373 Use STRICT_ASSIGN() for exp2f() and exp2() instead of a volatile
variable hack for exp2f() only.

The volatile variable had a surprisingly large cost for exp2f() -- 19
cycles or 15% on i386 in the worst case observed.  This is only partly
explained by there being several references to the variable, only one
of which benefited from it being volatile.  Arches that have working
assignment are likely to benefit even more from not having any volatile
variable.

exp2() now has a chance of working with extra precision on i386.

exp2() has even more references to the variable, so it would have been
pessimized more by simply declaring the variable as volatile.  Even
the temporary volatile variable for STRICT_ASSIGN costs 5-10% on i386,
(A64) so I will change STRICT_ASSIGN() to do an ordinary assignment
until i386 defaults to extra precision.
2008-01-19 21:37:14 +00:00
bde
3b6da800e8 Use STRICT_ASSIGN() for _kernel_rem_pio2f() and _kernel_rem_pio2f()
instead of a volatile cast hack for the float version only.  The cast
hack broke with gcc-4, but this was harmless since the float version
hasn't been used for a few years.  Merge from the float version so
that the double version has a chance of working on i386 with extra
precision.

See k_rem_pio2f.c rev.1.8 for the original hack.

Convert to _FBSDID().
2008-01-19 20:02:55 +00:00
bde
6d3cabaca6 Use STRICT_ASSIGN() for log1pf() and log1p() instead of a volatile cast
hack for log1pf() only.  The cast hack broke with gcc-4, resulting in
~1 million errors of more than 1 ulp, with a maximum error of ~1.5 ulps.
Now the maximum error for log1pf() on i386 is 0.5034 ulps again (this
depends on extra precision), and log1p() has a chance of working with
extra precision.

See s_log1pf.c 1.8 for the original hack.  (It claims only 62343 large
errors).

Convert to _FBSDID().  Another thing broken with gcc-4 is the static
const hack used for rcsids.
2008-01-19 18:13:21 +00:00
bde
aaee2ef564 Use STRICT_ASSIGN() instead of assorted direct volatile hacks to work
around assignments not working for gcc on i386.  Now volatile hacks
for rint() and rintf() don't needlessly pessimize so many arches
and the remaining pessimizations (for arm and powerpc) can be avoided
centrally.

This cleans up after s_rint.c 1.3 and 1.13 and s_rintf.c 1.3 and 1.9:
- s_rint.c 1.13 broke 1.3 by only using a volatile cast hack in 1 place
  when it was needed in 2 places, and the volatile cast hack stopped
  working with gcc-4.  These bugs only affected correctness tests on
  i386 since i386 normally uses asm rint() and doesn't support the
  extra precision mode that would break assignments of doubles.
- s_rintf.c 1.9 improved(?) on 1.3 by using a volatile variable hack
  instead of an extra-precision variable hack, but it declared 2
  variables as volatile when only 1 variable needed to be volatile.
  This only affected speed tests on i386 since i386 uses asm rintf().
2008-01-19 16:37:57 +00:00
das
6cc44c600b Use volatile hacks to make sure these functions generate an underflow
exception when they're supposed to. Previously, gcc -O2 was optimizing
away the statement that generated it.
2008-01-18 22:19:04 +00:00
das
71d083b685 Hook up exp2l() and related docs to the build. 2008-01-18 21:43:10 +00:00
das
8f7624b016 Introduce a new log(3) manpage and move the relevant functions there.
Document exp2l() in exp(3), and remove the quaint discussion of topics
such as what these functions were called on the HP-71B's variant of
BASIC.
2008-01-18 21:43:00 +00:00
das
0bde705160 Implement exp2l(). There is one version for machines with 80-bit
long doubles (i386, amd64, ia64) and one for machines with 128-bit
long doubles (sparc64). Other platforms use the double version.
I've only done runtime testing on i386.

Thanks to bde@ for helpful discussions and bugfixes.
2008-01-18 21:42:46 +00:00
bde
b9ae01c4c7 Add a macro STRICT_ASSIGN() to help avoid the compiler bug that
assignments and casts don't clip extra precision, if any.  The
implementation is to assign to a temporary volatile variable and read
the result back to assign to the original lvalue.

lib/msun currently 2 different hard-coded hacks to avoid the problem
in just a few places and needs it in a few more places.  One variant
uses volatile for the original lvalue.  This works but is slower than
necessary.  Another temporarily casts the lvalue to volatile.  This
broke with gcc-4.2.1 or earlier (gcc now stores to the lvalue but
doesn't load from it).
2008-01-17 17:02:11 +00:00
das
84df07987f Optimize this a bit better.
Submitted by:	bde (although these aren't all of his changes)
2008-01-15 23:31:24 +00:00
das
4f45aea521 Implement rintl(), nearbyintl(), lrintl(), and llrintl().
Thanks to bde@ for feedback and testing of rintl().
2008-01-14 02:12:07 +00:00
das
c7fe2c294a - Correct the range check in the double version to catch negative values
that would overflow.
- Style fixes and improved handling of NaNs suggested by bde.
2008-01-11 04:18:25 +00:00
das
85788af52a Grumble. DO declare logbl(), DON'T declare logl() just yet.
bde is going to commit logl() Real Soon Now.
I'm just trying to slow him down with merge conflicts.

Noticed by:	bde
2007-12-20 03:16:55 +00:00
das
662b60ede0 Remove the declaration of logl(). The relevant bits haven't been
committed yet, but the declaration leaked in when I added nan() and
friends.

Reported by:	pav
2007-12-20 00:06:33 +00:00
das
ac3245defa Since nan() is supposed to work the same as strtod("nan(...)", NULL),
my original implementation made both use the same code. Unfortunately,
this meant libm depended on a vendor header at compile time and previously-
unexposed vendor bits in libc at runtime.

Hence, I just wrote my own version of the relevant vendor routine. As it
turns out, mine has a factor of 8 fewer of lines of code, and is a bit more
readable anyway. The strtod() and *scanf() routines still use vendor code.

Reviewed by:	bde
2007-12-18 23:46:32 +00:00
das
bbeb8e278a Remove z_abs(). The z_*() functions were in libf77, and for some reason
someone thought it would be a good idea to copy z_abs() to libm in 1994.
However, it's never been declared or documented anywhere, and I'm
reasonably confident that nobody uses it.

Discussed with: bde, deischen, kan
2007-12-18 01:15:20 +00:00
bde
d71c22b712 Oops, the previous commit was not needed -- the file was committed but
not checked out due to my checkout error.
2007-12-17 18:21:23 +00:00
bde
23b7db74d0 Translate from the i386 so that this compiles and runs.
I hope that this and the i386 version of it will not be needed, but
this is currently about 16 cycles or 36% faster than the C version,
and the i386 version is about 8 cycles or 19% faster than the C
version, due to poor optimization of the C version.
2007-12-17 18:12:06 +00:00
bde
688e538772 Don't try to build s_nanl.c before it is committed. 2007-12-17 13:20:38 +00:00
das
d717f8cf06 Add logbl(3) to libm. 2007-12-17 03:53:38 +00:00
das
05daf4f2d4 Document the fact that we have nan(3) now, and make some minor clarifications
in other places.
2007-12-17 01:04:43 +00:00
das
bb384eba43 Implement and document nan(), nanf(), and nanl(). This commit
adds two new directories in msun: ld80 and ld128. These are for
long double functions specific to the 80-bit long double format
used on x86-derived architectures, and the 128-bit format used on
sparc64, respectively.
2007-12-16 21:19:28 +00:00
das
53fc314c85 1. Add csqrt{,f}(3).
2. Put carg{,f}(3) under the FBSD_1.1 namespace where it belongs
   (requested by kan@)
2007-12-15 08:39:03 +00:00
das
28907d1d2e Implement and document csqrt(3) and csqrtf(3). 2007-12-15 08:38:44 +00:00
das
a5d6580347 Update the standards section, and make a minor clarification about the
return value of sqrt.
2007-12-14 07:53:09 +00:00
das
1e3188021c Typo in previous commit 2007-12-14 03:08:10 +00:00
das
1b6fc1af81 Symbol.map additions for carg and cargf. (They're in C99, so I didn't
add a new version for them.)
2007-12-14 03:06:50 +00:00
das
4550e2583b s/C90/C99/ 2007-12-12 23:50:00 +00:00
das
937d496694 Add a "STANDARDS" section. 2007-12-12 23:49:40 +00:00
das
b9a043d44c Implement carg(3) and cargf(3).
Rotting in an old src tree since: March 2005
2007-12-12 23:43:51 +00:00
bde
fd5ba4c3e4 Oops, back out previous commit since it was backwards to a wrong branch. 2007-06-14 05:57:13 +00:00
bde
c1decaa9ff MFC: 1.11: fix the threshold for (not) using the simple Taylor approximation. 2007-06-14 05:51:00 +00:00
bde
c7b78b63db Fix an aliasing bug which was finally detected by gcc-4.2. fdlibm has
hundreds of similar aliasing bugs, but all except this one seem to have
been fixed by Cygnus and/or NetBSD before the modified version of fdlibm
was imported into FreeBSD in 1994.

PR:		standards/113147
Submitted by:	Steve Kargl <sgk@troutmask.apl.washington.edu>
2007-06-11 07:48:52 +00:00
bde
0cadc213d5 Merge the relevant part of rev.1.14 of s_cbrt.c (a micro-optimization
involving moving the check for x == 0).  The savings in cycles are
smaller for cbrtf() than for cbrt(), and positive in all measured cases
with gcc-3.4.4, but still very machine/compiler-dependent.
2007-05-29 07:13:07 +00:00
deischen
ff36458e08 Bump library versions in preparation for 7.0.
Ok'd by:	kan
2007-05-21 02:49:08 +00:00
deischen
bf3a79274d Enable symbol versioning by default. Use WITHOUT_SYMVER to disable it.
Warning, after symbol versioning is enabled, going back is not easy
(use WITHOUT_SYMVER at your own risk).

Change the default thread library to libthr.

There most likely still needs to be a version bump for at least the
thread libraries.  If necessary, this will happen later.
2007-05-13 14:12:40 +00:00
bde
7b4912a3de Don't assume that int is signed 32-bits in one place. Keep assuming
that ints have >= 31 value bits elsewhere.  s/int/int32_t/ seems to
have been done too globally for all other files in msun/src before
msun/ was imported into FreeBSD.

Minor fixes in comments.

e_lgamma_r.c:
Describe special cases in more detail:
- exception for lgamma(0) and lgamma(neg.integer)
- lgamma(-Inf) = Inf.  This is wrong but is required by C99 Annex F.  I
  hope to change this.
2007-05-02 16:54:22 +00:00
bde
f9978195dc Fix tgamma() on some special args:
(1) tgamma(-Inf) returned +Inf and failed to raise any exception, but
    should always have raised an exception, and should behave like
    tgamma(negative integer).
(2) tgamma(negative integer) returned +Inf and raised divide-by-zero,
    but should return NaN and raise "invalid" on any IEEEish system.
(3) About half of the 2**52 negative intgers between -2**53 and -2**52
    were misclassified as non-integers by using floor(x + 0.5) to round
    to nearest, so tgamma(x) was wrong (+-0 instead of +Inf and now NaN)
    on these args.  The floor() expression is hard to use since rounding
    of (x + 0.5) may give x or x + 1, depending on |x| and the current
    rounding mode.  The fixed version uses ceil(x) to classify x before
    operating on x and ends up being more efficient since ceil(x) is
    needed anyway.
(4) On at least the problematic args in (3), tgamma() raised a spurious
    inexact.
(5) tgamma(large positive) raised divide-by-zero but should raise overflow.
(6) tgamma(+Inf) raised divide-by-zero but should not raise any exception.
(7) Raise inexact for tiny |x| in a way that has some chance of not being
    optimized away.

The fix for (5) and (6), and probably for (2), also prevents -O optimizing
away the exception.

PR:		112180 (2)
Standards:	Annex F in C99 (IEC 60559 binding) requires (1), (2) and (6).
2007-05-02 15:24:49 +00:00
bde
98484906b6 Document (in a comment) the current (slightly broken) handling of special
values in more detail, and change the style of this comment to be closer
to fdlibm and C99:
- tgamma(-Inf) was undocumented and is wrong (+Inf, should be NaN)
- tgamma(negative integer) is as intended (+Inf) but not best for IEEE-754
  (NaN)
- tgamma(-0) was documented as being wrong (+Inf) but was correct (-Inf)
- documentation of setting of exceptions (overflow, etc.) was more
  complete here than in most of libm, but was further from matching
  the actual setting than in most of libm, due to various bugs here
  (primarily, always evaluating +Inf one/zero and getting unwanted
  divide-by-zero exceptions from this).  Now the actual behaviour with
  gcc -O0 is documented.  Optimization still breaks setting of exceptions
  all over libm, so nothing can depend on this working.
- tgamma(NaN)'s exception was documented as being wrong (invalid) but was
  correct (no exception with IEEEish NaNs).

Finish (?) rev.1.5.  gamma was not renamed to tgamma in one place.

Finish (?) rev.1.6.  errno.h was not completely removed.
2007-05-02 13:49:28 +00:00
deischen
2a7306fdc5 Use C comments since we now preprocess these files with CPP. 2007-04-29 14:05:22 +00:00
imp
130ae175fc Remove California Regent's clause 3, per letter 2007-01-09 01:02:06 +00:00
das
3ef4cfecda Implement modfl(). 2007-01-07 07:54:21 +00:00