Commit Graph

609 Commits

Author SHA1 Message Date
David Schultz
61f955827d 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
David Schultz
de336b0c5e 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
David Schultz
079299f710 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
Bruce Evans
63b4a1f80c 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
Bruce Evans
5014f8ded4 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
Bruce Evans
3365b45e5e 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
Bruce Evans
b4437c3d32 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
Bruce Evans
011cbae1fe 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
Bruce Evans
e7c95ee5fe s_ceill.c
s_floorl.c
s_truncl.c
2008-02-13 17:38:16 +00:00
Bruce Evans
74d68da630 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
Bruce Evans
6597187205 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
Bruce Evans
f01bfe5c6d 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
Bruce Evans
828f7b4a82 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
Bruce Evans
02ef796d23 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
Bruce Evans
a2ddfa5ea7 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
Bruce Evans
51f86873af 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
Bruce Evans
52453261e9 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
Bruce Evans
6d656800db Fix a comment about coefficients and expand a related one. 2008-02-09 10:36:07 +00:00
Bruce Evans
fbe8fb4d7b 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
Bruce Evans
aa7c7c47cf 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
Bruce Evans
a00672cff9 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
Bruce Evans
a373e66b85 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
Bruce Evans
ce56838fdc 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
David Schultz
b134ea7211 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
Bruce Evans
fc84b771b4 Fix a harmless type error in 1.9. 2008-01-25 21:09:21 +00:00
Bruce Evans
f2a1477818 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
Bruce Evans
85c309021f 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
Bruce Evans
a9b721d6b2 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
Bruce Evans
5b62c3808e 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
Bruce Evans
684217d889 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
Bruce Evans
fa7fdac725 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
Bruce Evans
0814af48f7 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
Bruce Evans
6a876b92fb 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
David Schultz
86c2e0c047 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
David Schultz
3d2cc91218 Hook up exp2l() and related docs to the build. 2008-01-18 21:43:10 +00:00
David Schultz
5526551600 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
David Schultz
968b39e3b9 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
Bruce Evans
1880ccbd79 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
David Schultz
a2d171e440 Optimize this a bit better.
Submitted by:	bde (although these aren't all of his changes)
2008-01-15 23:31:24 +00:00
David Schultz
d3f9671a7d Implement rintl(), nearbyintl(), lrintl(), and llrintl().
Thanks to bde@ for feedback and testing of rintl().
2008-01-14 02:12:07 +00:00
David Schultz
73b2958b94 - 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
David Schultz
45310fdb5d 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
David Schultz
58c9a67ed7 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
David Schultz
7cd4a83267 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
David Schultz
0ba1fd2f72 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
Bruce Evans
ccef8c4fcb 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
Bruce Evans
a18b106ffc 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
Bruce Evans
9ed67737f2 Don't try to build s_nanl.c before it is committed. 2007-12-17 13:20:38 +00:00
David Schultz
6821aba9e5 Add logbl(3) to libm. 2007-12-17 03:53:38 +00:00
David Schultz
3be0479b4c 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
David Schultz
4b6b574455 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
David Schultz
3c27af2a44 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
David Schultz
aaf70b2314 Implement and document csqrt(3) and csqrtf(3). 2007-12-15 08:38:44 +00:00
David Schultz
ce448a2e74 Update the standards section, and make a minor clarification about the
return value of sqrt.
2007-12-14 07:53:09 +00:00
David Schultz
80f974729f Typo in previous commit 2007-12-14 03:08:10 +00:00
David Schultz
39ebc398b6 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
David Schultz
9768c3fea8 s/C90/C99/ 2007-12-12 23:50:00 +00:00
David Schultz
367d55260f Add a "STANDARDS" section. 2007-12-12 23:49:40 +00:00
David Schultz
205bd64894 Implement carg(3) and cargf(3).
Rotting in an old src tree since: March 2005
2007-12-12 23:43:51 +00:00
Bruce Evans
b5e547df33 Oops, back out previous commit since it was backwards to a wrong branch. 2007-06-14 05:57:13 +00:00
Bruce Evans
d382c5ebb4 MFC: 1.11: fix the threshold for (not) using the simple Taylor approximation. 2007-06-14 05:51:00 +00:00
Bruce Evans
a8a2e00ebf 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
Bruce Evans
20a990117d 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
Daniel Eischen
419ecd5dee Bump library versions in preparation for 7.0.
Ok'd by:	kan
2007-05-21 02:49:08 +00:00
Daniel Eischen
00fb440c1a 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
Bruce Evans
9698b3b564 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
Bruce Evans
e95cc9b700 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
Bruce Evans
dd936b27fc 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
Daniel Eischen
5f864214bb Use C comments since we now preprocess these files with CPP. 2007-04-29 14:05:22 +00:00
Warner Losh
ee7093a640 Remove California Regent's clause 3, per letter 2007-01-09 01:02:06 +00:00
David Schultz
9abb1ff616 Implement modfl(). 2007-01-07 07:54:21 +00:00
David Schultz
8185b32b5a Fix a problem relating to fesetenv() clobbering i387 register stack.
Details: As a side-effect of restoring a saved FP environment,
fesetenv() overwrites the tag word, which indicates which i387
registers are in use.  Normally this isn't a problem because
the calling convention requires the register stack to be empty
on function entry and exit.  However, fesetenv() is inlined, so we
need to tell gcc explicitly that the i387 registers get clobbered.

PR:	85101
2007-01-06 21:46:23 +00:00
David Schultz
93e0663877 Fix a cut-and-paste-o. 2007-01-06 21:23:20 +00:00
David Schultz
829d55ac9c Correctly handle NaN. 2007-01-06 21:22:57 +00:00
David Schultz
9fa229fc8d Correctly handle inf/nan. This routine is currently unused because we
seem to have assembly versions for all architectures, but it can't
hurt to fix it.
2007-01-06 21:22:38 +00:00
David Schultz
6642c3fa74 Remove modf from libm's symbol map. It's actually in libc for
hysterical raisins.
2007-01-06 21:18:17 +00:00
David Schultz
3cb636ce18 Remove an unneeded fnstcw instruction.
Noticed by:	bde
2007-01-05 07:15:26 +00:00
David Schultz
cc0d85b680 Remove a note pertaining to the Alpha. 2007-01-05 07:14:26 +00:00
Bruce Evans
fae6222bdb Moved __BEGIN_DECLS up a little so that it covers __test_sse() and C++
isn't broken,

PR:		104425
2006-10-14 20:35:56 +00:00
Ruslan Ermilov
2b46c64c9c Remove alpha left-overs. 2006-08-22 08:03:01 +00:00
Bruce Evans
d79d610d9c Fixed the threshold for using the simple Taylor approximation.
In e_log.c, there was just a off-by-1 (1 ulp) error in the comment
about the threshold.  The precision of the threshold is unimportant,
but the magic numbers in the code are easier to understand when the
threshold is described precisely.

In e_logf.c, mistranslation of the magic numbers gave an off-by-1
(1 * 16 ulps) error in the intended negative bound for the threshold
and an off-by-7 (7 * 16 ulps) error in the intended positive bound for
the threshold, and the intended bounds were not translated from the
double precision bounds so they were unnecessarily small by a factor
of about 2048.

The optimization of using the simple Taylor approximation for args
near a power of 2 is dubious since it only applies to a relatively
small proportion of args, but if it is done then doing it 2048 times
as often _may_ be more efficient.  (My benchmarks show unexplained
dependencies on the data that increase with further optimizations
in this area.)
2006-07-07 04:33:08 +00:00
Bruce Evans
fe72622ebe Fixed tanh(-0.0) on ia64 and optimizeed tanh(x) for 2**-55 <= |x| <
2**-28 as a side effect, by merging with the float precision version
of tanh() and the double precision version of sinh().

For tiny x, tanh(x) ~= x, and we used the expression x*(one+x) to
return this value (x) and set the inexact flag iff x != 0.  This
doesn't work on ia64 since gcc -O does the dubious optimization
x*(one+x) = x+x*x so as to use fma, so the sign of -0.0 was lost.

Instead, handle tiny x in the same as sinh(), although this is imperfect:
- return x directly and set the inexact flag in a less efficient way.
- increased the threshold for non-tinyness from 2**-55 to 2**-28 so that
  many more cases are optimized than are pessimized.

Updated some comments and fixed bugs in others (ranges for half-open
intervals mostly had the open end backwards, and there were nearby style
bugs).
2006-07-05 22:59:33 +00:00
Bruce Evans
3454a5a101 Removed the optimized asm versions of scalb() and scalbf(). These
functions are only for compatibility with obsolete standards.  They
shouldn't be used, so they shouldn't be optimized.  Use the generic
versions instead.

This fixes scalbf() as a side effect.  The optimized asm version left
garbage on the FP stack.  I fixed the corresponding bug in the optimized
asm scalb() and scalbn() in 1996.  NetBSD fixed it in scalb(), scalbn()
and scalbnf() in 1999 but missed fixing it in scalbf().  Then in 2005
the bug was reimplemented in FreeBSD by importing NetBSD's scalbf().

The generic versions have slightly different error handling:
- the asm versions blindly round the second parameter to a (floating
  point) integer and proceed, while the generic versions return NaN
  if this rounding changes the value.  POSIX permits both behaviours
  (these functions are XSI extensions and the behaviour for a bogus
  non-integral second parameter is unspecified).   Apart from this
  and the bug in scalbf(), the behaviour of the generic versions seems
  to be identical.  (I only exhusatively tested
  generic_scalbf(1.0F, anyfloat) == asm_scalb(1.0F, anyfloat).  This
  covers many representative corner cases involving NaNs and Infs but
  doesn't test exception flags.  The brokenness of scalbf() showed up
  as weird behaviour after testing just 7 integer cases sequentially.)
2006-07-05 20:06:42 +00:00
Bruce Evans
8eca9455de Backed out rev.1.10. It tried to implement ldexpf() as a weak reference
to scalbf(), but ldexpf() cannot be implemented in that way since the
types of the second parameter differ.  ldexpf() can be implemented as
a weak or strong reference to scalbnf() (*) but that was already done
long before rev.1.10 was committed.  The old implementation uses a
reference, so rev.1.10 had no effect on applications.  The C files for
the scalb() family are not used for amd64 or i386, so rev.1.10 had even
less effect for these arches.

(*) scalbnf() raises the radix to the given exponent, while ldexpf()
raises 2 to the given exponent.  Thus the functions are equivalent
except possibly for their error handling iff the radix is 2.  Standards
more or less require identical error handling.  Under FreeBSD, the
functions are equivalent except for more details being missing in
scalbnf()'s man page.
2006-07-05 02:16:29 +00:00
Daniel Eischen
d7eda46253 Add symbol versioning to libm. 2006-03-27 23:59:45 +00:00
Bruce Evans
fd2891004d Oops, on amd64 (and probably on all non-i386 systems), the previous
commit broke the 2**24 cases where |x| > DBL_MAX/2.  There are exponent
range problems not just for denormals (underflow) but for large values
(overflow).  Doubles have more than enough exponent range to avoid the
problems, but I forgot to convert enough terms to double, so there was
an x+x term which was sometimes evaluated in float precision.

Unfortunately, this is a pessimization with some combinations of systems
and compilers (it makes no difference on Athlon XP's, but on Athlon64's
it gives a 5% pessimization with gcc-3.4 but not with gcc-3.3).

Exlain the problem better in comments.
2006-01-05 09:18:48 +00:00
Bruce Evans
4bb9780353 Use double precision internally to optimize cbrtf(), and change the
algorithm for the second step significantly to also get a perfectly
rounded result in round-to-nearest mode.  The resulting optimization
is about 25% on Athlon64's and 30% on Athlon XP's (about 25 cycles
out of 100 on the former).

Using extra precision, we don't need to do anything special to avoid
large rounding errors in the third step (Newton's method), so we can
regroup terms to avoid a division, increase clarity, and increase
opportunities for parallelism.  Rearrangement for parallelism loses
the increase in clarity.  We end up with the same number of operations
but with a division reduced to a multiplication.

Using specifically double precision, there is enough extra precision
for the third step to give enough precision for perfect rounding to
float precision provided the previous steps are accurate to 16 bits.
(They were accurate to 12 bits, which was almost minimal for imperfect
rounding in the old version but would be more than enough for imperfect
rounding in this version (9 bits would be enough now).)  I couldn't
find any significant time optimizations from optimizing the previous
steps, so I decided to optimize for accuracy instead.  The second step
needed a division although a previous commit optimized it to use a
polynomial approximation for its main detail, and this division dominated
the time for the second step.  Use the same Newton's method for the
second step as for the third step since this is insignificantly slower
than the division plus the polynomial (now that Newton's method only
needs 1 division), significantly more accurate, and simpler.  Single
precision would be precise enough for the second step, but doesn't
have enough exponent range to handle denormals without the special
grouping of terms (as in previous versions) that requires another
division, so we use double precision for both the second and third
steps.
2006-01-05 07:57:31 +00:00
Bruce Evans
5776f433ab Extract the high and low words together. With gcc-3.4 on uniformly
distributed non-large args, this saves about 14 of 134 cycles for
Athlon64s and about 5 of 199 cycles for AthlonXPs.

Moved the check for x == 0 inside the check for subnormals.  With
gcc-3.4 on uniformly distributed non-large args, this saves another
5 cycles on Athlon64s and loses 1 cycle on AthlonXPs.

Use INSERT_WORDS() and not SET_HIGH_WORD() when converting the first
approximation from bits to double.  With gcc-3.4 on uniformly distributed
non-large args, this saves another 4 cycles on both Athlon64s and and
AthlonXPs.

Accessing doubles as 2 words may be an optimization on old CPUs, but on
current CPUs it tends to cause extra operations and pipeline stalls,
especially for writes, even when only 1 of the words needs to be accessed.

Removed an unused variable.
2005-12-20 01:21:30 +00:00
Bruce Evans
c5964538b7 Use a minimax polynomial approximation instead of a Pade rational
function approximation for the second step.  The polynomial has degree
2 for cbrtf() and 4 for cbrt().  These degrees are minimal for the final
accuracy to be essentially the same as before (slightly smaller).
Adjust the rounding between steps 2 and 3 to match.  Unfortunately,
for cbrt(), this breaks the claimed accuracy slightly although incorrect
rounding doesn't.  Claim less accuracy since its not worth pessimizing
the polynomial or relying on exhaustive testing to get insignificantly
more accuracy.

This saves about 30 cycles on Athlons (mainly by avoiding 2 divisions)
so it gives an overall optimization in the 10-25% range (a larger
percentage for float precision, especially in 32-bit mode, since other
overheads are more dominant for double precision, surprisingly more
in 32-bit mode).
2005-12-19 00:22:03 +00:00
Bruce Evans
ce804bff58 Fixed code to match comments and the algorithm:
- in preparing for the third approximation, actually make t larger in
  magnitude than cbrt(x).  After chopping, t must be incremented by 2
  ulps to make it larger, not 1 ulp since chopping can reduce it by
  almost 1 ulp and it might already be up to half a different-sized-ulp
  smaller than cbrt(x).  I have not found any cases where this is
  essential, but the think-time error bound depends on it.  The relative
  smallness of the different-sized-ulp limited the bug.  If there are
  cases where this is essential, then the final error bound would be
  5/6+epsilon instead of of 4/6+epsilon ulps (still < 1).
- in preparing for the third approximation, round more carefully (but
  still sloppily to avoid branches) so that the claimed error bound of
  0.667 ulps is satisfied in all cases tested for cbrt() and remains
  satisfied in all cases for cbrtf().  There isn't enough spare precision
  for very sloppy rounding to work:
  - in cbrt(), even with the inadequate increment, the actual error was
    0.6685 in some cases, and correcting the increment increased this
    a little.  The fix uses sloppy rounding to 25 bits instead of very
    sloppy rounding to 21 bits, and starts using uint64_t instead of 2
    words for bit manipulation so that rounding more bits is not much
    costly.
  - in cbrtf(), the 0.667 bound was already satisfied even with the
    inadequate increment, but change the code to almost match cbrt()
    anyway.  There is not enough spare precision in the Newton
    approximation to double the inadequate increment without exceeding
    the 0.667 bound, and no spare precision to avoid this problem as
    in cbrt().  The fix is to round using an increment of 2 smaller-ulps
    before chopping so that an increment of 1 ulp is enough.  In cbrt(),
    we essentially do the same, but move the chop point so that the
    increment of 1 is not needed.

Fixed comments to match code:
- in cbrt(), the second approximation is good to 25 bits, not quite 26 bits.
- in cbrt(), don't claim that the second approximation may be implemented
  in single precision.  Single precision cannot handle the full exponent
  range without minor but pessimal changes to renormalize, and although
  single precision is enough, 25 bit precision is now claimed and used.

Added comments about some of the magic for the error bound 4/6+epsilon.
I still don't understand why it is 4/6+ and not 6/6+ ulps.

Indent comments at the right of code more consistently.
2005-12-18 21:46:47 +00:00
Bruce Evans
7aac169e18 Added comments about the apparently-magic rational function used in
the second step of approximating cbrt(x).  It turns out to be neither
very magic not nor very good.  It is just the (2,2) Pade approximation
to 1/cbrt(r) at r = 1, arranged in a strange way to use fewer operations
at a cost of replacing 4 multiplications by 1 division, which is an
especially bad tradeoff on machines where some of the multiplications
can be done in parallel.  A Remez rational approximation would give
at least 2 more bits of accuracy, but the (2,2) Pade approximation
already gives 6 more bits than needed.  (Changed the comment which
essentially says that it gives 3 more bits.)

Lower order Pade approximations are not quite accurate enough for
double precision but are plenty for float precision.  A lower order
Remez rational approximation might be enough for double precision too.
However, rational approximations inherently require an extra division,
and polynomial approximations work well for 1/cbrt(r) at r = 1, so I
plan to switch to using the latter.  There are some technical
complications that tend to cost a division in another way.
2005-12-15 16:23:22 +00:00
Bruce Evans
ec761d7501 Optimize by not doing excessive conversions for handling the sign bit.
This gives an optimization of between 9 and 22% on Athlons (largest
for cbrt() on amd64 -- from 205 to 159 cycles).

We extracted the sign bit and worked with |x|, and restored the sign
bit as the last step.  We avoided branches to a fault by using accesses
to FP values as bits to clear and restore the sign bit.  Avoiding
branches is usually good, but the bit access macros are not so good
(especially for setting FP values), and here they always caused pipeline
stalls on Athlons.  Even using branches would be faster except on args
that give perfect branch misprediction, since only mispredicted branches
cause stalls, but it possible to avoid touching the sign bit in FP
values at all (except to preserve it in conversions from bits to FP
not related to the sign bit).  Do this.  The results are identical
except in 2 of the 3 unsupported rounding modes, since all the
approximations use odd rational functions so they work right on strictly
negative values, and the special case of -0 doesn't use an approximation.
2005-12-13 20:17:23 +00:00
Bruce Evans
7d5a4821ba Fixed some especially horrible style bugs (indentation that is neither
KNF nor fdlibmNF combined with multiple statements per line).
2005-12-13 18:22:00 +00:00
Bruce Evans
af7f99131d Added comments about the magic behind
<cbrt(x) in bits> ~= <x in bits>/3 + BIAS.
Keep the large comments only in the double version as usual.

Fixed some style bugs (mainly grammar and spelling errors in comments).
2005-12-11 19:51:30 +00:00
Bruce Evans
288a8c86cb Fixed the unexpectedly large maximum error after the previous commit.
It was because I forgot to translate the part of the double precision
algorithm that chops t so that t*t is exact.  Now the maximum error
is the same as for double precision (almost exactly 2.0/3 ulps).
2005-12-11 17:58:14 +00:00
Bruce Evans
6de073b4ef Fixed all 502518670 errors of more than 1 ulp for cbrtf() on amd64.
The maximum error was 3.56 ulps.

The bug was another translation error.  The double precision version
has a comment saying "new cbrt to 23 bits, may be implemented in
precision".  This means exactly what it says -- that the 23 bit second
approximation for the double precision cbrt() may be implemented in
single (i.e., float) precision.  It doesn't mean what the translation
assumed -- that this approximation, when implemented in float precision,
is good enough for the the final approximation in float precision.
First, float precision needs a 24 bit approximation.  The "23 bit"
approximation is actually good to 24 bits on float precision args, but
only if it is evaluated in double precision.  Second, the algorithm
requires a cleanup step to ensure its error bound.

In float precision, any reasonable algorithm works for the cleanup
step.  Use the same algorithm as for double precision, although this
is much more than enough and is a significant pessimization, and don't
optimize or simplify anything using double precision to implement the
float case, so that the whole double precision algorithm can be verified
in float precision.  A maximum error of 0.667 ulps is claimed for cbrt()
and the max for cbrtf() using the same algorithm shouldn't be different,
but the actual max for cbrtf() on amd64 is now 0.9834 ulps.  (On i386
-O1 the max is 0.5006 (down from < 0.7) due to extra precision.)
2005-12-11 13:22:01 +00:00
Bruce Evans
1a787460ba Fixed some magic numbers.
The threshold for not being tiny was too small.  Use the usual 2**-12
threshold.  As for sinhf, use a different method (now the same as for
sinhf) to set the inexact flag for tiny nonzero x so that the larger
threshold works, although this method is imperfect.  As for sinhf,
this change is not just an optimization, since the general code that
we fell into has accuracy problems even for tiny x.  On amd64, avoiding
it fixes tanhf on 2*13495596 args with errors of between 1 and 1.3
ulps and thus reduces the total number of args with errors of >= 1 ulp
from 37533748 to 5271278; the maximum error is unchanged at 2.2 ulps.

The magic number 22 is log(DBL_MAX)/2 plus slop.  This is bogus for
float precision.  Use 9 (log(FLT_MAX)/2 plus less slop than for
double precision).  Unlike for coshf and tanhf, this is just an
optimization, and MAX isn't misspelled EPSILON in the commit log.

I started testing with nonstandard rounding modes, and verified that
the chosen thresholds work for all modes modulo problems not related
to thresholds.  The best thresholds are not very dependent on the mode,
at least for tanhf.
2005-12-11 11:40:55 +00:00
David E. O'Brien
9b39b7cba6 "Create" ldexpf for non-i386 architectures.
Submitted by:	Steve Kargl <sgk@troutmask.apl.washington.edu>
2005-12-06 20:12:38 +00:00
Bruce Evans
0f06be5a4d Fixed the approximation to pio4. pio4_hi must be pio2_hi/2 since it
shares its low half with pio2_hi.  pio2_hi is rounded down although
rounding to nearest would be a tiny bit better, so pio4_hi must be
rounded down too.  It was rounded to nearest, which happens to be
different in float precision but the same in double precision.

This fixes about 13.5 million errors of more than 1 ulp in asinf().
The largest error was 2.81 ulps on amd64 and 2.57 ulps on i386 -O1.
Now the largest error is 0.93 ulps on amd65 and 0.67 ulps on i386 -O1.
2005-12-04 13:52:46 +00:00
Bruce Evans
d48ea9753c For log1pf(), fixed the approximations to sqrt(2), sqrt(2)-1 and
sqrt(2)/2-1.  For log1p(), fixed the approximation to sqrt(2)/2-1.

The end result is to fix an error of 1.293 ulps in
    log1pf(0.41421395540 (hex 0x3ed413da))
and an error of 1.783 ulps in
    log1p(-0.292893409729003961761) (hex 0x12bec4 00000001)).
The former was the only error of > 1 ulp for log1pf() and the latter
is the only such error that I know of for log1p().

The approximations don't need to be very accurate, but the last 2 need
to be related to the first and be rounded up a little (even more than
1 ulp for sqrt(2)/2-1) for the following implementation-detail reason:
when the arg (x) is not between (the approximations to) sqrt(2)/2-1
and sqrt(2)-1, we commit to using a correction term, but we only
actually use it if 1+x is between sqrt(2)/2 and sqrt(2) according to
the first approximation. Thus we must ensure that
!(sqrt(2)/2-1 < x < sqrt(2)-1) implies !(sqrt(2)/2 < x+1 < sqrt(2)),
where all the sqrt(2)'s are really slightly different approximations
to sqrt(2) and some of the "<"'s are really "<="'s.  This was not done.

In log1pf(), the last 2 approximations were rounded up by about 6 ulps
more than needed relative to a good approximation to sqrt(2), but the
actual approximation to sqrt(2) was off by 3 ulps.  The approximation
to sqrt(2)-1 ended up being 4 ulps too small, so the algoritm was
broken in 4 cases.  The result happened to be broken in 1 case.  This
is fixed by using a natural approximation to sqrt(2) and derived
approximations for the others.

In logf(), all the approximations made sense, but the approximation
to sqrt(2)/2-1 was 2 ulps too small (a tiny amount, since we compare
with a granularity of 2**32 ulps), so the algorithm was broken in 2
cases.  The result was broken in 1 case.  This is fixed by rounding
up the approximation to sqrt(2)/2-1 by 2**32 ulps, so 2**32 cases are
now handled a little differently (still correctly according to my
assertion that the approximations don't need to be very accurate, but
this has not been checked).
2005-12-04 12:30:44 +00:00
Bruce Evans
669152498a Use the usual volatile hack to trick gcc into clipping any extra precision
on assignment.

Extra precision on i386's broke hi+lo decomposition in the usual way.
It caused all except 1 of the 62343 errors of more than 1 ulp for
log1pf() on i386's with gcc -O [-fno-float-store].
2005-12-04 08:57:54 +00:00
Bruce Evans
00b1756b1e Fixed fdlibm[+cygnus] logbf() and logb() on denormals. Adjustment
according to the highest nonzero bit in a denormal was missing.

fdlibm ilogbf() and ilogb() have always had the adjustment, but only
use a small part of their method for handling denormals; use the
normalization method in log[f]() for the main part.
2005-12-03 11:57:19 +00:00
Bruce Evans
1186054263 Restored removal of the special handling needed for a result of +-0.
It was lost in rev.1.9.  The log message for rev.1.9 says that the
special case of +-0 is handled twice, but it was only handled once,
so it became unhandled, and this happened to break half of the cases
that return +-0:
- round-towards-minus-infinity:  0   <  x < 1:  result was -0 not  0
- round-to-nearest:             -0.5 <= x < 0:  result was  0 not -0
- round-towards-plus-infinity:  -1   <  x < 0:  result was  0 not -0
- round-towards-zero:           -1   <  x < 0:  result was  0 not -0
2005-12-03 09:00:29 +00:00
Bruce Evans
3fc5a433e9 Simplified the fix in rev.1.3. Instead of using long double for
TWO52[sx] to trick gcc into correctly converting TWO52[sx]+x to double
on assignment to "double w", force a correct assignment by assigning
to *(double *)&w.  This is cleaner and avoids the double rounding
problem on machines that evaluate double expressions in double
precision.  It is not necessary to convert w-TWO52[sx] to double
precision on return as implied in the comment in rev.1.3, since
the difference is exact.
2005-12-03 07:38:35 +00:00
Bruce Evans
7441377544 Fixed rint(x) in the following cases:
(1) In round-to-nearest mode, on all machines, fdlibm rint() never
    worked for |x| = n+0.75 where n is an even integer between 262144
    and 524286 inclusive (2*131072 cases).  To avoid double rounding
    on some machines, we begin by adjusting x to a value with the 0.25
    bit not set, essentially by moving the 0.25 bit to a lower bit
    where it works well enough as a guard, but we botched the adjustment
    when log2(|x|) == 18 (2*2**52 cases) and ended up just clearing
    the 0.25 bit then.  Most subcases still worked accidentally since
    another lower bit serves as a guard.  The case of odd n worked
    accidentally because the rounding goes the right way then.  However,
    for even n, after mangling n+0.75 to 0.5, rounding gives n but the
    correct result is n+1.
(2) In round-towards-minus-infinity mode, on all machines, fdlibm rint()
    never for x = n+0.25 where n is any integer between -524287 and
    -262144 inclusive (262144 cases).  In these cases, after mangling
    n+0.25 to n, rounding gives n but the correct result is n-1.
(3) In round-towards-plus-infinity mode, on all machines, fdlibm rint()
    never for x = n+0.25 where n is any integer between 262144 and
    524287 inclusive (262144 cases).  In these cases, after mangling
    n+0.25 to n, rounding gives n but the correct result is n+1.

A variant of this bug was fixed for the float case in rev.1.9 of s_rintf.c,
but the analysis there is incomplete (it only mentions (1)) and the fix
is buggy.

Example of the problem with double rounding: rint(1.375) on a machine
which evaluates double expressions with just 1 bit of extra precision
and is in round-to-nearest mode.  We evaluate the result using
(double)(2**52 + 1.375) - 2**52.  Evaluating 2**52 + 1.375 in (53+1) bit
prcision gives 2**52 + 1.5 (first rounding).  (Second) rounding of this
to double gives 2**52 + 2.0.  Subtracting 2**52 from this gives 2.0 but
we want 1.0.  Evaluating 2**52 + 1.375 in double precision would have
given the desired intermediate result of 2**52 + 1.0.

The double rounding problem is relatively rare, so the botched adjustment
can be fixed for most machines by removing the entire adjustment.  This
would be a wrong fix (using it is 1 of the bugs in rev.1.9 of s_rintf.c)
since fdlibm is supposed to be generic, but it works in the following cases:
- on all machines that evaluate double expressions in double precision,
  provided either long double has the same precision as double (alpha,
  and i386's with precision forced to double) or my earlier fix to use
  a long double 2**52 is modified to avoid using long double precision.
- on all machines that evaluate double expressions in many more than 11
  bits of extra precision.  The 1 bit of extra precision in the example
  is the worst case.  With N bits of extra precision, it sufices to
  adjust the bit N bits below the 0.5 bit.  For N >= about 52 there is
  no such bit so the adjustment is both impossible and unnecessary.  The
  fix in rev.1.9 of s_rintf.c apparently depends on corresponding magic
  in float precision: on all supported machines N is either 0 or >= 24,
  so double rounding doesn't occur in practice.
- on all machines that don't use fdlibm rint*() (i386's).
So under FreeBSD, the double rounding problem only affects amd64 now, but
should only affect i386 in future (when double expressions are evaluated
in long double precision).
2005-12-03 07:23:30 +00:00
Bruce Evans
5792e54aa9 Fixed roundf(). The following cases never worked in FreeBSD:
- in round-towards-minus-infinity mode, on all machines, roundf(x) never
  worked for 0 < |x| < 0.5 (2*0x3effffff cases in all, or almost half of
  float space).  It was -0 for 0 < x < 0.5 and 0 for -0.5 < x < 0, but
  should be 0 and -0, respectively.  This is because t = ceilf(|x|) = 1
  for these args, and when we adjust t from 1 to 0 by subtracting 1, we
  get -0 in this rounding mode, but we want and expected to get 0.
- in round-towards-minus-infinity, round towards zero and round-to-nearest
  modes, on machines that evaluate float expressions in float precision
  (most machines except i386's), roundf(x) never worked for |x| =
  <float value immediately below 0.5> (2 cases in all).  It was +-1 but
  should have been +-0.  This is because t = ceilf(|x|) = 1 for these
  args, and when we try to classify |x| by subtracting it from 1 we
  get an unexpected rounding error -- the result is 0.5 after rounding
  to float in all 3 rounding modes, so we we have forgotten the
  difference between |x| and 0.5 and end up returning the same value
  as for +-0.5.

The fix is to use floorf() instead of ceilf() and to add 1 instead of
-1 in the adjustment.  With floorf() all the expressions used are
always evaluated exactly so there are no rounding problems, and with
adjustments of +1 we don't go near -0 when adjusting.

Attempted to fix round() and roundl() by cloning the fix for roundf().
This has only been tested for round(), only on args representable as
floats.  Double expressions are evaluated in double precision even on
i386's, so round(0.5-epsilon) was broken even on i386's.  roundl()
must be completely broken on i386's since long double precision is not
really supported.  There seem to be no other dependencies on the
precision.
2005-12-02 13:45:06 +00:00
Bruce Evans
f4b01a9edf Rearranged the polynomial evaluation to reduce dependencies, as in
k_tanf.c but with different details.

The polynomial is odd with degree 13 for tanf() and odd with degree
9 for sinf(), so the details are not very different for sinf() -- the
term with the x**11 and x**13 coefficients goes awaym and (mysteriously)
it helps to do the evaluation of w = z*z early although moving it later
was a key optimization for tanf().  The details are different but simpler
for cosf() because the polynomial is even and of lower degree.

On Athlons, for uniformly distributed args in [-2pi, 2pi], this gives
an optimization of about 4 cycles (10%) in most cases (13% for sinf()
on AXP, but 0% for cosf() with gcc-3.3 -O1 on AXP).  The best case
(sinf() with gcc-3.4 -O1 -fcaller-saves on A64) now takes 33-39 cycles
(was 37-45 cycles).  Hardware sinf takes 74-129 cycles.  Despite
being fine tuned for Athlons, the optimization is even larger on
some other arches (about 15% on ia64 (pluto2) and 20% on alpha (beast)
with gcc -O2 -fomit-frame-pointer).
2005-11-30 11:51:17 +00:00
Bruce Evans
8d3b309bad Fixed cosf(x) when x is a "negative" NaNs. I broke this in rev.1.10.
cosf(x) is supposed to return something like x when x is a NaN, and
we actually fairly consistently return x-x which is normally very like
x (on i386 and and it is x if x is a quiet NaN and x with the quiet bit
set if x is a signaling NaN.  Rev.1.10 broke this by normalising x to
fabsf(x).  It's not clear if fabsf(x) is should preserve x if x is a NaN,
but it actually clears the sign bit, and other parts of the code depended
on this.

The bugs can be fixed by saving x before normalizing it, and using the
saved x only for NaNs, and using uint32_t instead of int32_t for ix
so that negative NaNs are not misclassified even if fabsf() doesn't
clear their sign bit, but gcc pessimizes the saving very well, especially
on Athlon XPs (it generates extra loads and stores, and mixes use of
the SSE and i387, and this somehow messes up pipelines).  Normalizing
x is not a very good optimization anyway, so stop doing it.  (It adds
latency to the FPU pipelines, but in previous versions it helped except
for |x| <= 3pi/4 by simplifying the integer pipelines.)  Use the same
organization as in s_sinf.c and s_tanf.c with some branches reordered.
These changes combined recover most of the performance of the unfixed
version on A64 but still lose 10% on AXP with gcc-3.4 -O1 but not with
gcc-3.3 -O1.
2005-11-30 06:47:18 +00:00
Bruce Evans
908801933a Fixed the hi+lo approximation to log(2). The normal 17+24 bit decomposition
that was used doesn't work normally here, since we want to be able to
multiply `hi' by the exponent of x _exactly_, and the exponent of x has
more than 7 significant bits for most denormal x's, so the multiplication
was not always exact despite a cloned comment claiming that it was.  (The
comment is correct in the double precision case -- with the normal 33+53
bit decomposition the exponent can have 20 significant bits and the extra
bit for denormals is only the 11th.)

Fixing this had little or no effect for denormals (I think because
more precision is inherently lost for denormals than is lost by roundoff
errors in the multiplication).

The fix is to reduce the precision of the decomposition to 16+24 bits.
Due to 2 bugs in the old deomposition and numerical accidents, reducing
the precision actually increased the precision of hi+lo.  The old hi+lo
had about 39 bits instead of at least 41 like it should have had.
There were off-by-1-bit errors in each of hi and lo, apparently due
to mistranslation from the double precision hi and lo.  The correct
16 bit hi happens to give about 19 bits of precision, so the correct
hi+lo gives about 43 bits instead of at least 40.  The end result is
that expf() is now perfectly rounded (to nearest) except in 52561 cases
instead of except in 67027 cases, and the maximum error is 0.5013 ulps
instead of 0.5023 ulps.
2005-11-30 04:56:49 +00:00
Bruce Evans
1dd21062e5 Rearranged the polynomial evaluation some more to reduce dependencies.
Instead of echoing the code in a comment, try to describe why we split
up the evaluation in a special way.

The new optimization is mostly to move the evaluation of w = z*z later
so that everything else (except z = x*x) doesn't have to wait for w.
On Athlons, FP multiplication has a latency of 4 cycles so this
optimization saves 4 cycles per call provided no new dependencies are
introduced.  Tweaking the other terms in to reduce dependencies saves
a couple more cycles in some cases (more on AXP than on A64; up to 8
cycles out of 56 altogether in some cases).  The previous version had
a similar optimization for s = z*x.  Special optimizations like these
probably have a larger effect than the simple 2-way vectorization
permitted (but not activated by gcc) in the old version, since 2-way
vectorization is not enough and the polynomial's degree is so small
in the float case that non-vectorizable dependencies dominate.

On an AXP, tanf() on uniformly distributed args in [-2pi, 2pi] now
takes 34-55 cycles (was 39-59 cycles).
2005-11-28 11:46:20 +00:00
Bruce Evans
671448d87e Fixed about 50 million errors of infinity ulps and about 3 million errors
of between 1.0 and 1.8509 ulps for lgammaf(x) with x between -2**-21 and
-2**-70.

As usual, the cutoff for tiny args was not correctly translated to
float precision.  It was 2**-70 but 2**-21 works.  Not as usual, having
a too-small threshold was worse than a pessimization.  It was just a
pessimization for (positive) args between 2**-70 and 2**-21, but for
the first ~50 million (negative) args below -2**-70, the general code
overflowed and gave a result of infinity instead of correct (finite)
results near 70*log(2).  For the remaining ~361 million negative args
above -2**21, the general code gave almost-acceptable errors (lgamma[f]()
is not very accurate in general) but the pessimization was larger than
for misclassified tiny positive args.

Now the max error for lgammaf(x) with |x| < 2**-21 is 0.7885 ulps, and
speed and accuracy are almost the same for positive and negative args
in this range.  The maximum error overall is still infinity ulps.

A cutoff of 2**-70 is probably wastefully small for the double precision
case.  Smaller cutoffs can be used to reduce the max error to nearly
0.5 ulps for tiny args, but this is useless since the general algrorithm
for nearly-tiny args is not nearly that accurate -- it has a max error of
about 1 ulp.
2005-11-28 08:32:15 +00:00
Bruce Evans
0bea84b2d4 Exploit skew-symmetry to avoid an operation: -sin(x-A) = sin(A-x). This
gives a tiny but hopefully always free optimization in the 2 quadrants
to which it applies.  On Athlons, it reduces maximum latency by 4 cycles
in these quadrants but has usually has a smaller effect on total time
(typically ~2 cycles (~5%), but sometimes 8 cycles when the compiler
generates poor code).
2005-11-28 06:15:10 +00:00
Bruce Evans
35ae347641 Try to use the "proximity" (~) operator consistently in comments
(x ~<= a, not x <= ~a).  This got messed up in some places when the
comments were moved from e_rem_pio2f.c.

Added my (non-)copyright.
2005-11-28 05:46:13 +00:00
Bruce Evans
960d3da0f0 Changed spelling of the request-to-inline macro name to match the change
of the function name.

Added my (non-)copyright.

In k_tanf.c, added the first set of redundant parentheses to control
grouping which was claimed to be added in the previous commit.
2005-11-28 05:35:32 +00:00
Bruce Evans
59aad933ab Use only double precision for "kernel" cosf and sinf (except for
returning float).  The functions are renamed from __kernel_{cos,sin}f()
to __kernel_{cos,sin}df() so that misuses of them will cause link errors
and not crashes.

This version is an almost-routine translation with no special optimizations
for accuracy or efficiency.  The not-quite-routine part is that in
__kernel_cosf(), regenerating the minimax polynomial with double
precision coefficients gives a coefficient for the x**2 term that is
not quite -0.5, so the literal 0.5 in the code and the related `hz'
variable need to be modified; also, the special code for reducing the
error in 1.0-x**2*0.5 is no longer needed, so it is convenient to
adjust all the logic for the x**2 term a little.  Note that without
extra precision, it would be very bad to use a coefficient of other
than -0.5 for the x**2 term -- the old version depends on multiplication
by -0.5 being infinitely precise so as not to need even more special
code for reducing the error in 1-x**2*0.5.

This gives an unimportant increase in accuracy, from ~0.8 to ~0.501
ulps.  Almost all of the error is from the final rounding step, since
the choice of the minimax polynomials so that their contribution to the
error is a bit less than 0.5 ulps just happens to give contributions that
are significantly less (~.001 ulps).

An Athlons, for uniformly distributed args in [-2pi, 2pi], this gives
overall speed increases in the 10-20% range, despite giving a speed
decrease of typically 19% (from 31 cycles up to 37) for sinf() on args
in [-pi/4, pi/4].
2005-11-28 04:58:57 +00:00
Bruce Evans
833f0e1a4a Minor cleanups and optimizations:
- Remove dead code that I forgot to remove in the previous commit.

- Calculate the sum of the lower terms of the polynomial (divided by
  x**5) in a single expression (sum of odd terms) + (sum of even terms)
  with parentheses to control grouping.  This is clearer and happens to
  give better instruction scheduling for a tiny optimization (an
  average of about ~0.5 cycles/call on Athlons).

- Calculate the final sum in a single expression with parentheses to
  control grouping too.  Change the grouping from
  first_term + (second_term + sum_of_lower_terms) to
  (first_term + second_term) + sum_of_lower_terms.  Normally the first
  grouping must be used for accuracy, but extra precision makes any
  grouping give a correct result so we can group for efficiency.  This
  is a larger optimization (average 3-4 cycles/call or 5%).

- Use parentheses to indicate that the C order of left to right evaluation
  is what is wanted (for efficiency) in a multiplication too.

The old fdlibm code has several optimizations related to these.  2
involve doing an extra operation that can be done almost in parallel
on some superscalar machines but are pessimizations on sequential
machines.  Others involve statement ordering or expression grouping.
All of these except the ordering for the combining the sums of the odd
and even terms seem to be ideal for Athlons, but parallelism is still
limited so all of these optimizations combined together with the ones
in this commit save only ~6-8 cycles (~10%).

On an AXP, tanf() on uniformly distributed args in [-2pi, 2pi] now
takes 39-59 cycles.  I don't know of any more optimizations for tanf()
short of writing it all in asm with very MD instruction scheduling.
Hardware fsin takes 122-138 cycles.  Most of the optimizations for
tanf() don't work very well for tan[l]().  fdlibm tan() now takes
145-365 cycles.
2005-11-24 13:48:40 +00:00
Joel Dahl
19797b2256 s/5.5/6.0/ in HISTORY section.
Discussed with:	ru
2005-11-24 09:25:10 +00:00
Bruce Evans
16638b5585 Optimized by eliminating the special case for 0.67434 <= |x| < pi/4.
A single polynomial approximation for tan(x) works in infinite precision
up to |x| < pi/2, but in finite precision, to restrict the accumulated
roundoff error to < 1 ulp, |x| must be restricted to less than about
sqrt(0.5/((1.5+1.5)/3)) ~= 0.707.  We restricted it a bit more to
give a safety margin including some slop for optimizations.  Now that
we use double precision for the calculations, the accumulated roundoff
error is in double-precision ulps so it can easily be made almost 2**29
times smaller than a single-precision ulp.  Near x = pi/4 its maximum
is about 0.5+(1.5+1.5)*x**2/3 ~= 1.117 double-precision ulps.

The minimax polynomial needs to be different to work for the larger
interval.  I didn't increase its degree the old degree is just large
enough to keep the final error less than 1 ulp and increasing the
degree would be a pessimization.  The maximum error is now ~0.80
ulps instead of ~0.53 ulps.

The speedup from this optimization for uniformly distributed args in
[-2pi, 2pi] is 28-43% on athlons, depending on how badly gcc selected
and scheduled the instructions in the old version.  The old version
has some int-to-float conversions that are apparently difficult to schedule
well, but gcc-3.3 somehow did everything ~10 cycles or ~10% faster than
gcc-3.4, with the difference especially large on AXPs.  On A64s, the
problem seems to be related to documented penalties for moving single
precision data to undead xmm registers.  With this version, the speed
is cycles is almost independent of the athlon and gcc version despite
the large differences in instruction selection to use the FPU on AXPs
and SSE on A64s.
2005-11-24 02:04:26 +00:00
Bruce Evans
94a5f9be99 Use only double precision for "kernel" tanf (except for returning float).
This is a minor interface change.  The function is renamed from
__kernel_tanf() to __kernel_tandf() so that misues of it will cause
link errors and not crashes.

This version is a routine translation with no special optimizations
for accuracy or efficiency.  It gives an unimportant increase in
accuracy, from ~0.9 ulps to 0.5285 ulps.  Almost all of the error is
from the minimax polynomial (~0.03 ulps and the final rounding step
(< 0.5 ulps).  It gives strange differences in efficiency in the -5
to +10% range, with -O1 fairly consistently becoming faster and -O2
slower on AXP and A64 with gcc-3.3 and gcc-3.4.
2005-11-23 14:27:56 +00:00
Bruce Evans
01231dd04c Simplified setiing up args for __kernel_rem_pio2(). We already have x
with a 24-bit fraction, so we don't need a loop to split it into up to
3 terms with 24-bit fractions.
2005-11-23 03:03:09 +00:00
Bruce Evans
33f8f56e09 Quick fix for stack buffer overrun in rev.1.13. Oops. The prec == 1
arg to __kernel_rem_pio2() gives 53-bit (double) precision, not single
precision and/or the array dimension like I thought.  prec == 2 is
used in e_rem_pio2.c for double precision although it is documented
to be for 64-bit (extended) precision, and I just reduced it by 1
thinking that this would give the value suitable for 24-bit (float)
precision.  Reducing it 1 more to the documented value for float
precision doesn't actually work (it gives errors of ~0.75 ulps in the
reduced arg, but errors of much less than 0.5 ulps are needed; the bug
seems to be in kernel_rem_pio2.c).  Keep using a value 1 larger than
the documented value but supply an array large enough hold the extra
unused result from this.

The bug can also be fixed quickly by increasing init_jk[0] in
k_rem_pio2.c from 2 to 3.  This gives behaviour identical to using
prec == 1 except it doesn't create the extra result.  It isn't clear
how the precision bug affects higher precisions.  113-bit (quad) is
the largest precision, so there is no way to use a large precision
to fix it.
2005-11-23 02:06:06 +00:00
Bruce Evans
4ce5120952 Mess up the "kernel" float trig function .c files with ifdefs so that
they can be #included in other .c files to give inline functions, and
use them to inline the functions in most callers (not in e_lgammaf_r.c).
__kernel_tanf() is too large and complicated for gcc to inline very well.

An athlons, this gives a speed increase under favourable pipeline
conditions of about 10% overall (larger for AXP, smaller for A64).
E.g., on AXP, sinf() on uniformly distributed args in [-2Pi, 2Pi]
now takes 30-56 cycles; it used to take 45-61 cycles; hardware fsin
takes 65-129.
2005-11-21 04:57:12 +00:00
Bruce Evans
58652034e8 Use double precision to simplify and optimize a long division.
On athlons, this gives a speedup of 10-20% for tanf() on uniformly
distributed args in [-2Pi, 2Pi].  (It only directly applies for 43%
of the args and gives a 16-20% speedup for these (more for AXP than
A64) and this gives an overall speedup of 10-12% which is all that it
should; however, it gives an overall speedup of 17-20% with gcc-3.3
on AXP-A64 by mysteriously effected cases where it isn't executed.)

I originally intended to use double precision for all internals of
float trig functions and will probably still do this, but benchmarking
showed that converting to double precision and back is a pessimization
in cases where a simple float precision calculation works, so it may
be optimal to switch precisions only when using extra precision is
much simpler.
2005-11-21 00:38:21 +00:00
Bruce Evans
23f6483e0a Restored a cleanup in rev.1.9 tthat was lost in rev.1.10. 2005-11-20 20:17:04 +00:00
Bruce Evans
8299eb7e3e Moved all the optimizations for |x| <= 9pi/2 from
__ieee754_rem_pio2f() to its 3 callers and manually inline them.

On Athlons, with favourable compiler flags and optimizations and
favourable pipeline conditions, this gives a speedup of 30-40 cycles
for cosf(), sinf() and tanf() on the range pi/4 < |x| <= 9pi/4, so
thes functions are now signifcantly faster than the hardware trig
functions in many cases.  E.g., in a benchmark with uniformly distributed
x in [-2pi, 2pi], A64 hardware fcos took 72-129 cycles and cosf() took
37-55 cycles.  Out-of-order execution is needed to get both of these
times.  The optimizations in this commit apparently work more by
removing 1 serialization point than by reducing latency.
2005-11-19 02:38:27 +00:00
Bruce Evans
3f1a8f462c Removed an unused declaration which was so old that it wasn't a prototype
and thus just broke building at any nonzero WARNS level.

Fixed nearby style bugs.
2005-11-18 05:03:12 +00:00
Ruslan Ermilov
110e1704d3 -mdoc sweep. 2005-11-17 13:00:00 +00:00
Bruce Evans
75ff209cbb Minor cleanups:
s_cosf.c and s_sinf.c:
Use a non-bogus magic constant for the threshold of pi/4.  It was 2 ulps
smaller than pi/4 rounded down, but its value is not critical so it should
be the result of natural rounding.

s_cosf.c and s_tanf.c:
Use a literal 0.0 instead of an unnecessary variable initialized to
[(float)]0.0.  Let the function prototype convert to 0.0F.

Improved wording in some comments.

Attempted to improve indentation of comments.
2005-11-17 03:53:22 +00:00
Bruce Evans
123e5d3dae Rearranged the the optimizations for special cases to reduce the average
number of branches.

Use a non-bogus magic constant for the threshold of pi/4.  It was 2 ulps
smaller than pi/4 rounded down, but its value is not critical so it should
be the result of natural rounding.  Use "<=" comparisons with rounded-
down thresholds for all small multiples of pi/4.

Cleaned up previous commit:
- use static const variables instead of expressions for multiples of pi/2
  to ensure that they are evaluated at compile time.  gcc currently
  evaluates them at compile time but C99 compilers are not required
  to do so.  We want compile time evaluation for optimization and don't
  care about side effects.
- use M_PI_2 instead of a magic constant for pi/2.  We need magic constants
  related to pi/2 elsewhere but not here since we just want pi/2 rounded
  to double and even prefer it to be rounded in the default rounding mode.
  We can depend on the cmpiler being C99ish enough to round M_PI_2 correctly
  just as much as we depended on it handling hex constants correctly.  This
  also fixes a harmless rounding error in the hex constant.
- keep using expressions n*<value for pi/2> in the initializers for the
  static const variables.  2*M_PI_2 and 4*M_PI_2 are obviously rounded in
  the same way as the corresponding infinite precision expressions for
  multiples of pi/2, and 3*M_PI_2 happens to be rounded like this, so we
  don't need magic constants for the multiples.
- fixed and/or updated some comments.
2005-11-17 02:20:04 +00:00
Bruce Evans
25efbfb212 Fixed some magic numbers.
The threshold for not being tiny was too small.  Use the usual 2**-12
threshold.  This change is not just an optimization, since the general
code that we fell into has accuracy problems even for tiny x.  Avoiding
it fixes 2*1366 args with errors of more than 1 ulp, with a maximum
error of 1.167 ulps.

The magic number 22 is log(DBL_EPSILON)/2 plus slop.  This is bogus
for float precision.  Use 9 (~log(FLT_EPSILON)/2 plus less slop than
for double precision).  The code for handling the interval
[2**-28, 9_was_22] has accuracy problems even for [9, 22], so this
change happens to fix errors of more than 1 ulp in about 2*17000
cases.  It leaves such errors in about 2*1074000 cases, with a max
error of 1.242 ulps.

The threshold for switching from returning exp(x)/2 to returning
exp(x/2)^2/2 was a little smaller than necessary.  As for coshf(),
This was not quite harmless since the exp(x/2)^2/2 case is inaccurate,
and fixing it avoids accuracy problems in 2*6 cases, leaving problems
in 2*19997 cases.

Fixed naming errors in pseudo-code in comments.
2005-11-13 00:41:46 +00:00
Bruce Evans
c24b7984fc Fixed some magic numbers.
The threshold for not being tiny was confusing and too small.  Use the
usual 2**-12 threshold and simplify the algorithm slightly so that
this threshold works (now use the threshold for sinhf() instead of one
for 1+expm1()).  This is just a small optimization.

The magic number 22 is log(DBL_EPSILON)/2 plus slop.  This is bogus
for float precision.  Use 9 (~log(FLT_EPSILON)/2 plus less slop than
for double precision).

The threshold for switching from returning exp(x)/2 to returning
exp(x/2)^2/2 was a little smaller than necessary.  This was not quite
harmless since the exp(x/2)^2/2 case is inaccurate.  Fixing it happens
to avoid accuracy problems for 2*6 of the 2*151 args that were handled
by the exp(x)/2 case.  This leaves accuracy problems for about 2*19997
args near the overflow threshold (~89); the maximum error there is
2.5029 ulps.

There are also accuracy probles for args in +-[0.5*ln2, 9] -- 2*188885
args with errors of more than 1 ulp, with a maximum error of 1.384 ulps.

Fixed a syntax error and naming errors in pseudo-code in comments.
2005-11-13 00:08:23 +00:00
Bruce Evans
e96c4fd9f7 Imoproved comments for the minimax polynomial.
Removed an unused variable.

Fixed some wrong comments and some nearby misformatting.
2005-11-12 20:06:04 +00:00
Bruce Evans
6e10a447f8 Tweaked the minimax polynomial and improved its comments. 2005-11-12 19:56:35 +00:00
Bruce Evans
787d6d77d5 Improved comments for the minimax polynomial. 2005-11-12 19:54:45 +00:00
Bruce Evans
d4a74de9fc As for the float trig functions, use a minimax polynomial that is
specialized for float precision.  The new polynomial has degree 8
instead of 14, and a maximum error of 2**-34.34 (absolute) instead of
2**-30.66.  This doesn't affect the final error significantly; the
maximum error was and is about 0.8879 ulps on amd64 -01.

The fdlibm expf() is not used on i386's (the "optimized" asm version
is used), but probably should be since it was already significantly
faster than the asm version on athlons.  The asm version has the
advantage of being more accurate, so keep using it for now.
2005-11-12 18:20:09 +00:00
Bruce Evans
c01611e437 As for __kernel_cosf() and __kernel_sinf(), use a fairly optimal minimax
polynomial for __kernel_tanf().  The old one was the double-precision
polynomial with coefficients truncated to float.  Truncation is not
a good way to convert minimax polynomials to lower precision.  Optimize
for efficiency and use the lowest-degree polynomial that gives a
relative error of less than 1 ulp.  It has degree 13 instead of 27,
and happens to be 2.5 times more accurate (in infinite precision) than
the old polynomial (the maximum error is 0.017 ulps instead of 0.041
ulps).

Unlike for cosf and sinf, the old accuracy was close to being inadequate
-- the polynomial for double precision has a max error of 0.014 ulps
and nearly this small an error is needed.  The new accuracy is also a
bit small, but exhaustive checking shows that even the old accuracy
was enough.  The increased accuracy reduces the maximum relative error
in the final result on amd64 -O1 from 0.9588 ulps to 0.9044 ulps.
2005-11-10 17:43:49 +00:00
Bruce Evans
2b6ca0f6a5 Detach k_rem_pio2f.c from the build since it is now unused. It is a libm
internal so this shouldn't cause version problems.
2005-11-06 17:59:40 +00:00
Bruce Evans
efff995f3b Use a 53-bit approximation to pi/2 instead of a 33+53 bit one for the
special case pi/4 <= |x| < 3*pi/4.  This gives a tiny optimization (it
saves 2 subtractions, which are scheduled well so they take a whole 1
cycle extra on an AthlonXP), and simplifies the code so that the
following optimization is not so ugly.

Optimize for the range 3*pi/4 < |x| < 9*Pi/2 in the same way.  On
Athlon{XP,64} systems, this gives a 25-40% optimization (depending a
lot on CFLAGS) for the cosf() and sinf() consumers on this range.
Relative to i387 hardware fcos and fsin, it makes the software versions
faster in most cases instead of slower in most cases.  The relative
optimization is smaller for tanf() the inefficient part is elsewhere.

The 53-bit approximation to pi/2 is good enough for pi/4 <= |x| <
3*pi/4 because after losing up to 24 bits to subtraction, we still
have 29 bits of precision and only need 25 bits.  Even with only 5
extra bits, it is possible to get perfectly rounded results starting
with the reduced x, since if x is nearly a multiple of pi/2 then x is
not near a half-way case and if x is not nearly a multiple of pi/2
then we don't lose many bits.  With our intentionally imperfect rounding
we get the same results for cosf(), sinf() and tanf() as without this
optimization.
2005-11-06 17:48:02 +00:00
Bruce Evans
32948b81c4 The logb() functions are not just ieee754 "test" functions, but are
standard in C99 and POSIX.1-2001+.  They are also not deprecated, since
apart from being standard they can handle special args slightly better
than the ilogb() functions.

Move their documentation to ilogb.3.  Try to use consistent and improved
wording for both sets of functions.  All of ieee854, C99 and POSIX
have better wording and more details for special args.

Add history for the logb() functions and ilogbl().  Fix history for
ilogb().
2005-11-06 12:18:27 +00:00
Bruce Evans
cb92d4d58f Moved the optimization for tiny x from __kernel_tan[f](x) to tan[f](x)
so that it can be faster for tiny x and avoided for reduced x.

This improves things a little differently than for cosine and sine.
We still need to reclassify x in the "kernel" functions, but we get
an extra optimization for tiny x, and an overall optimization since
tiny reduced x rarely happens.  We also get optimizations for space
and style.  A large block of poorly duplicated code to fix a special
case is no longer needed.  This supersedes the fixes in k_sin.c revs
1.9 and 1.11 and k_sinf.c 1.8 and 1.10.

Fixed wrong constant for the cutoff for "tiny" in tanf().  It was
2**-28, but should be almost the same as the cutoff in sinf() (2**-12).
The incorrect cutoff protected us from the bugs fixed in k_sinf.c 1.8
and 1.10, except 4 cases of reduced args passed the cutoff and needed
special handling in theory although not in practice.  Now we essentially
use a cutoff of 0 for the case of reduced args, so we now have 0 special
args instead of 4.

This change makes no difference to the results for sinf() (since it
only changes the algorithm for the 4 special args and the results for
those happen not to change), but it changes lots of results for sin().
Exhaustive testing is impossible for sin(), but exhaustive testing
for sinf() (relative to a version with the old algorithm and a fixed
cutoff) shows that the changes in the error are either reductions or
from 0.5-epsilon ulps to 0.5+epsilon ulps.  The new method just uses
some extra terms in approximations so it tends to give more accurate
results, and there are apparently no problems from having extra
accuracy.  On amd64 with -O1, on all float args the error range in ulps
is reduced from (0.500, 0.665] to [0.335, 0.500) in 24168 cases and
increased from 0.500-epsilon to 0.500+epsilon in 24 cases.  Non-
exhaustive testing by ucbtest shows no differences.
2005-11-02 14:01:45 +00:00
Bruce Evans
4f8d68d6ca Updated the comment about the optimization for tiny x (the previous
commit moved it).  This includes a comment that the "kernel" sine no
longer works on arg -0, so callers must now handle this case.  The kernel
sine still works on all other tiny args; without the optimization it is
just a little slower on these args.  I intended it to keep working on
all tiny args, but that seems to be impossible without losing efficiency
or accuracy.  (sin(x) ~ x * (1 + S1*x**2 + ...) would preserve -0, but
the approximation must be written as x + S1*x**3 + ... for accuracy.)
2005-11-02 13:06:49 +00:00
Bruce Evans
639a1e1106 Removed dead code for handling tan[f]() on odd multiples of pi/2. This
case never occurs since pi/2 is irrational so no multiple of it can
be represented as a float and we have precise arg reduction so we never
end up with a remainder of 0 in the "kernel" function unless the
original arg is 0.

If this case occurs, then we would now fall through to general code
that returns +-Inf (depending on the sign of the reduced arg) instead
of forcing +Inf.  The correct handling would be to return NaN since
we would have lost so much precision that the correct result can be
anything _except_ +-Inf.

Don't reindent the else clause left over from this, although it was already
bogusly indented ("if (foo) return; else ..." just marches the indentation
to the right), since it will be removed too.

Index: k_tan.c
===================================================================
RCS file: /home/ncvs/src/lib/msun/src/k_tan.c,v
retrieving revision 1.10
diff -r1.10 k_tan.c
88,90c88
< 			if (((ix | low) | (iy + 1)) == 0)
< 				return one / fabs(x);
< 			else {
---
> 			{
2005-11-02 06:45:21 +00:00
Bruce Evans
16622bffd4 Fixed some of the silliness related to rev.1.8. In 1.8, "double" in
a declaration was not translated to "float" although bit fiddling on
double variables was translated.  This resulted in garbage being put
into the low word of one of the doubles instead of non-garbage being
put into the only word of the intended float.  This had no effect on
any result because:
- with doubles, the algorithm for calculating -1/(x+y) is unnecessarily
  complicated.  Just returning -1/((double)x+y) would work, and the
  misdeclaration gave something like that except for messing up some
  low bits with the bit fiddling.
- doubles have plenty of bits to spare so messing up some of the low
  bits is unlikely to matter.
- due to other bugs, the buggy code is reached for a whole 4 args out
  of all 2**32 float args.  The bug fixed by 1.8 only affects a small
  percentage of cases and a small percentage of 4 is 0.  The 4 args
  happen to cause no problems without 1.8, so they are even less likely
  to be affected by the bug in 1.8 than average args; in fact, neither
  1.8 nor this commit makes any difference to the result for these 4
  args (and thus for all args).

Corrections to the log message in 1.8: the bug only applies to tan()
and not tanf(), not because the float type can't represent numbers
large enough to trigger the problem (e.g., the example in the fdlibm-5.3
readme which is > 1.0e269), but because:
- the float type can't represent small enough numbers.  For there to be
  a possible problem, the original arg for tanf() must lie very near an
  odd multiple of pi/2.  Doubles can get nearer in absolute units.  In
  ulps there should be little difference, but ...
- ... the cutoff for "small" numbers is bogus in k_tanf.c.  It is still
  the double value (2**-28).  Since this is 32 times smaller than
  FLT_EPSILON and large float values are not very uniformly distributed,
  only 6 args other than ones that are initially below the cutoff give
  a reduced arg that passes the cutoff (the 4 problem cases mentioned
  above and 2 non-problem cases).

Fixing the cutoff makes the bug affect tanf() and much easier to detect
than for tan().  With a cutoff of 2**-12 on amd64 with -O1, 670102
args pass the cutoff; of these, there are 337604 cases where there
might be an error of >= 1 ulp and 5826 cases where there is such an
error; the maximum error is 1.5382 ulps.

The fix in 1.8 works with the reduced cutoff in all cases despite the
bug in it.  It changes the result in 84492 cases altogether to fix the
5826 broken cases.  Fixing the fix by translating "double" to "float"
changes the result in 42 cases relative to 1.8.  In 24 cases the
(absolute) error is increased and in 18 cases it is reduced, but it
remains less than 1 ulp in all cases.
2005-11-02 05:37:31 +00:00
Bruce Evans
053d1689b1 Fixed spelling of remquof() in its prototype. 2005-10-30 12:34:58 +00:00
Bruce Evans
f964c6ecfb Fixed some comments added in rev.1.5.
The log message for 1.5 said that some small (one or two ulp) inaccuracies
were fixed, and a comment implied that the critical change is to switch
the rounding mode to to-nearest, with a switch of the precision to
extended at no extra cost.  Actually, the errors are very large (ucbtest
finds ones of several hundred ulps), and it is the switch of the
precision that is critical.

Another comment was wrong about NaNs being handled sloppily.
2005-10-30 12:21:02 +00:00
Bruce Evans
19b114da0e Implement inline functions to give the complex result x+I*y from float
or double args x and y.  x+I*y cannot be used directly yet due to compiler
bugs.

Submitted by:	Steve Kargl <sgk@troutmask.apl.washington.edu>
2005-10-29 17:14:11 +00:00
Bruce Evans
8b438ea8dd Use double precision to simplify and optimize arg reduction for small
and medium size args too: instead of conditionally subtracting a float
17+24, 17+17+24 or 17+17+17+24 bit approximation to pi/2, always
subtract a double 33+53 bit one.  The float version is now closer to
the double version than to old versions of itself -- it uses the same
33+53 bit approximation as the simplest cases in the double version,
and where the float version had to switch to the slow general case at
|x| == 2^7*pi/2, it now switches at |x| == 2^19*pi/2 the same as the
double version.

This speeds up arg reduction by a factor of 2 for |x| between 3*pi/4 and
2^7*pi/4, and by a factor of 7 for |x| between 2^7*pi/4 and 2^19*pi/4.
2005-10-29 16:34:50 +00:00
Bruce Evans
21b0341c80 Start trying to make the float precision trig functions actually worth
using under FreeBSD.  Before this commit, all float precision functions
except exp2f() were implemented using only float precision, apparently
because Cygnus needed this in 1993 for embedded systems with slow or
inefficient double precision.  For FreeBSD, except possibly on systems
that do floating point entirely in software (very old i386 and now
arm), this just gives a more complicated implementation, many bugs,
and usually worse performance for float precision than for double
precision.  The bugs and worse performance were particulary large in
arg reduction for trig functions.  We want to divide by an approximation
to pi/2 which has as many as 1584 bits, so we should use the widest
type that is efficient and/or easy to use, i.e., double.  Use fdlibm's
__kernel_rem_pio2() to do this as Sun apparently intended.  Cygnus's
k_rem_pio2f.c is now unused.  e_rem_pio2f.c still needs to be separate
from e_rem_pio2.c so that it can be optimized for float args.  Similarly
for long double precision.

This speeds up cosf(x) on large args by a factor of about 2.  Correct
arg reduction on large args is still inherently very slow, so hopefully
these args rarely occur in practice.  There is much more efficiency
to be gained by using double precision to speed up arg reduction on
medium and small float args.
2005-10-29 08:15:29 +00:00
Bruce Evans
11dc241777 Use fairly optimal minimax polynomials for __kernel_cosf() and
__kernel_sinf().  The old ones were the double-precision polynomials
with coefficients truncated to float.  Truncation is not a good way
to convert minimax polynomials to lower precision.  Optimize for
efficiency and use the lowest-degree polynomials that give a relative
error of less than 1 ulp -- degree 8 instead of 14 for cosf and degree
9 instead of 13 for sinf.  For sinf, the degree 8 polynomial happens
to be 6 times more accurate than the old degree 14 one, but this only
gives a tiny amount of extra accuracy in results -- we just need to
use a a degree high enough to give a polynomial whose relative accuracy
in infinite precision (but with float coefficients) is a small fraction
of a float ulp (fdlibm generally uses 1/32 for the small fraction, and
the fraction for our degree 8 polynomial is about 1/600).

The maximum relative errors for cosf() and sinf() are now 0.7719 ulps
and 0.7969 ulps, respectively.
2005-10-28 13:36:58 +00:00
Bruce Evans
3b46e988e7 Use a better algorithm for reducing the error in __kernel_cos[f]().
This supersedes the fix for the old algorithm in rev.1.8 of k_cosf.c.

I want this change mainly because it is an optimization.  It helps
make software cos[f](x) and sin[f](x) faster than the i387 hardware
versions for small x.  It is also a simplification, and reduces the
maximum relative error for cosf() and sinf() on machines like amd64
from about 0.87 ulps to about 0.80 ulps.  It was validated for cosf()
and sinf() by exhaustive testing.  Exhaustive testing is not possible
for cos() and sin(), but ucbtest reports a similar reduction for the
worst case found by non-exhaustive testing.  ucbtest's non-exhaustive
testing seems to be good enough to find problems in algorithms but not
maximum relative errors when there are spikes.  E.g., short runs of
it find only 3 ulp error where the i387 hardware cos() has an error
of about 2**40 ulps near pi/2.
2005-10-26 12:36:18 +00:00
Bruce Evans
a92cb60b4e More fixes for arg reduction near pi/2 on systems with broken assignment
to floats (mainly i386's).  All errors of more than 1 ulp for float
precision trig functions were supposed to have been fixed; however,
compiling with gcc -O2 uncovered 18250 more such errors for cosf(),
with a maximum error of 1.409 ulps.

Use essentially the same fix as in rev.1.8 of k_rem_pio2f.c (access a
non-volatile variable as a volatile).  Here the -O1 case apparently
worked because the variable is in a 2-element array and it takes -O2
to mess up such a variable by putting it in a register.

The maximum error for cosf() on i386 with gcc -O2 is now 0.5467 (it
is still 0.5650 with gcc -O1).  This shows that -O2 still causes some
extra precision, but the extra precision is now good.

Extra precision is harmful mainly for implementing extra precision in
software.  We want to represent x+y as w+r where both "+" operations
are in infinite precision and r is tiny compared with w.  There is a
standard algorithm for this (Knuth (1981) 4.2.2 Theorem C), and fdlibm
uses this routinely, but the algorithm requires w and r to have the
same precision as x and y.  w is just x+y (calculated in the same
finite precision as x and y), and r is a tiny correction term.  The
i386 gcc bugs tend to give extra precision in w, and then using this
extra precision in the calculation of r results in the correction
mostly staying in w and being missing from r.  There still tends to
be no problem if the result is a simple expression involving w and r
-- modulo spills, w keeps its extra precision and r remains the right
correction for this wrong w.  However, here we want to pass w and r
to extern functions.  Extra precision is not retained in function args,
so w gets fixed up, but the change to the tiny r is tinier, so r almost
remains as a wrong correction for the right w.
2005-10-25 12:13:37 +00:00
Bruce Evans
4339c67c48 Moved the optimization for tiny x from __kernel_{cos,sin}[f](x) to
{cos_sin}[f](x) so that x doesn't need to be reclassified in the
"kernel" functions to determine if it is tiny (it still needs to be
reclassified in the cosine case for other reasons that will go away).

This optimization is quite large for exponentially distributed x, since
x is tiny for almost half of the domain, but it is a pessimization for
uniformally distributed x since it takes a little time for all cases
but rarely applies.  Arg reduction on exponentially distributed x
rarely gives a tiny x unless the reduction is null, so it is best to
only do the optimization if the initial x is tiny, which is what this
commit arranges.  The imediate result is an average optimization of
1.4% relative to the previous version in a case that doesn't favour
the optimization (double cos(x) on all float x) and a large
pessimization for the relatively unimportant cases of lgamma[f][_r](x)
on tiny, negative, exponentially distributed x.  The optimization should
be recovered for lgamma*() as part of fixing lgamma*()'s low-quality
arg reduction.

Fixed various wrong constants for the cutoff for "tiny".  For cosine,
the cutoff is when x**2/2! == {FLT or DBL}_EPSILON/2.  We round down
to an integral power of 2 (and for cos() reduce the power by another
1) because the exact cutoff doesn't matter and would take more work
to determine.  For sine, the exact cutoff is larger due to the ration
of terms being x**2/3! instead of x**2/2!, but we use the same cutoff
as for cosine.  We now use a cutoff of 2**-27 for double precision and
2**-12 for single precision.  2**-27 was used in all cases but was
misspelled 2**27 in comments.  Wrong and sloppy cutoffs just cause
missed optimizations (provided the rounding mode is to nearest --
other modes just aren't supported).
2005-10-24 14:08:36 +00:00
Bruce Evans
74bbe8ed42 Fixed range reduction for large multiples of pi/2 on systems with
broken assignment to floats (e.g., i386 with gcc -O, but not amd64 or
ia64; i386 with gcc -O0 worked accidentally).

Use an unnamed volatile temporary variable to trick gcc -O into clipping
extra precision on assignment.  It's surprising that only 1 place needed
to be changed.

For tanf() on i386 with gcc -O, the bug caused errors > 1 ulp with a
density of 2.3% for args larger in magnitude than 128*pi/2, with a
maximum error of 1.624 ulps.

After this fix, exhaustive testing shows that range reduction for
floats works as intended assuming that it is in within a factor of
about 2^16 of working as intended for doubles.  It provides >= 8
extra bits of precision for all ranges.  On i386:

range                       max error in double/single ulps    extra precision
-----                       -------------------------------    ---------------
0 to 3*pi/4                 0x000d3132  /  0.0016              9+ bits
3*pi/4 to 128*pi/2          0x00160445  /  0.0027              8+
128*pi/2 to +Inf            0x00000030  /  0.00000009          23+
128*pi/2 up, -O0 before fix 0x00000030  /  0.00000009          23+
128*pi/2 up, -O1 before fix 0x10000000  /  0.5                 1

The 23+ bits of extra precision for large multiples corresponds to almost
perfect reduction to a pair of floats (24 extra would be perfect).

After this fix, the maximum relative error (relative to the corresponding
fdlibm double precision function) is < 1 ulp for all basic trig functions
on all 2^32 float args on all machines tested:

          amd64     ia64      i386-O0   i386-O1
	  ------    ------    ------    ------
cosf:     0.8681    0.8681    0.7927    0.5650
sinf:     0.8733    0.8610    0.7849    0.5651
tanf:     0.9708    0.9329    0.9329    0.7035
2005-10-11 07:56:05 +00:00
Bruce Evans
59b8fc1535 Fixed range reduction near (but not very near) medium-sized multiples
of pi/2 (1 line) and expand a comment about related magic (many lines).

The bug was essentially the same as for the +-pi/2 case (a mistranslated
mask), but was smaller so it only significantly affected multiples
starting near +-13*pi/2.  At least on amd64, for cosf() on all 2^32
float args, the bug caused 128 errors of >= 1 ulp, with a maximum error
of 1.2393 ulps.
2005-10-10 20:02:02 +00:00
Bruce Evans
11cba99f67 Fix numerous errors of >= 1 ulp for cosf(x) and sinf(x) (1 line)
and add a comment about related magic (many lines)).

__kernel_cos[f]() needs a trick to reduce the error to below 1 ulp
when |x| >= 0.3 for the range-reduced x.  Modulo other bugs, naive
code that doesn't use the trick would have an error of >= 1 ulp
in about 0.00006% of cases when |x| >= 0.3 for the unreduced x,
with a maximum relative error of about 1.03 ulps.  Mistransation
of the trick from the double precision case resulted in errors in
about 0.2% of cases, with a maximum relative error of about 1.3 ulps.

The mistranslation involved not doing implicit masking of the 32-bit
float word corresponding to to implicit masking of the lower 32-bit
double word by clearing it.

sinf() uses __kernel_cosf() for half of all cases so its errors from
this bug are similar.  tanf() is not affected.

The error bounds in the above and in my other recent commit messages
are for amd64.  Extra precision for floats on i386's accidentally masks
this bug, but only if k_cosf.c is compiled with -O.  Although the extra
precision helps here, this is accidental and depends on longstanding
gcc precision bugs (not clipping extra precision on assignment...),
and the gcc bugs are mostly avoided by compiling without -O.  I now
develop libm mainly on amd64 systems to simplify error detection and
debugging.
2005-10-09 21:07:23 +00:00
Bruce Evans
a0e34da09f Oops, the last-minute optimization in rev.1.8 wasn't a good idea. The
17+17+24 bit pi/2 must only be used when subtraction of the first 2
terms in it from the arg is exact.  This happens iff the the arg in
bits is one of the 2**17[-1] values on each side of (float)(pi/2).

Revert to the algorithm in rev.1.7 and only fix its threshold for using
the 3-term pi/2.  Use the threshold that maximizes the number of values
for which the 3-term pi/2 is used, subject to not changing the algorithm
for comparing with the threshold.  The 3-term pi/2 ends up being used
for about half of its usable range (about 64K values on each side).
2005-10-09 04:29:08 +00:00
Bruce Evans
cd604283af Fixed syntax error (a missing brace) in previous commit. 2005-10-08 22:55:36 +00:00
Bruce Evans
a7b8acac04 Fixed range reduction near (but not very near) +-pi/2. A bug caused
a maximum error of 2.905 ulps for cosf(), but the algorithm for cosf()
is good for < 1 ulps and happens to give perfect rounding (< 0.5 ulps)
near +-pi/2 except for the bug.  The extra relative errors for tanf()
were similar (slightly larger).  The bug didn't affect sinf() since
sinf'(+-pi/2) is 0.

For range reduction in ~[-3pi/4, -pi/4] and ~[pi/4, 3pi/4] we must
subtract +-pi/2 and the only complication is that this must be done
in extra precision.  We have handy 17+24-bit and 17+17+24-bit
approximations to pi/2.  If we always used the former then we would
lose up to 24 bits of accuracy due to cancelation of leading bits, but
we need to keep at least 24 bits plus a guard digit or 2, and should
keep as many guard bits as efficiency permits.  So we used the
less-precise pi/2 not very near +-pi/2 and switched to using the
more-precise pi/2 very near +-pi/2.  However, we got the threshold for
the switch wrong by allowing 19 bits to cancel, so we ended up with
only 21 or 22 bits of accuracy in some cases, which is even worse than
naively subtracting pi/2 would have done.

Exhaustive checking shows that allowing only 17 bits to cancel (min.
accuracy ~24 bits) is sufficient to reduce the maximum error for cosf()
near +-pi/2 to 0.726 ulps, but allowing only 6 bits to cancel (min.
accuracy ~35-bits) happens to give perfect rounding for cosf() at
little extra cost so we prefer that.

We actually (in effect) allow 0 bits to cancel and always use the
17+17+24-bit pi/2 (min. accuracy ~41 bits).  This is simpler and
probably always more efficient too.  Classifying args to avoid using
this pi/2 when it is not needed takes several extra integer operations
and a branch, but just using it takes only 1 FP operation.

The patch also fixes misspelling of 17 as 24 in many comments.

For the double-precision version, the magic numbers include 33+53 bits
for the less-precise pi/2 and (53-32-1 = 20) bits being allowed to
cancel, so there are ~33-20 = 13 guard bits.  This is sufficient except
probably for perfect rounding.  The more-precise pi/2 has 33+33+53
bits and we still waste time classifying args to avoid using it.

The bug is apparently from mistranslation of the magic 32 in 53-32-1.
The number of bits allowed to cancel is not critical and we use 32 for
double precision because it allows efficient classification using a
32-bit comparison.  For float precision, we must use an explicit mask,
and there are fewer bits so there is less margin for error in their
allocation.  The 32 got reduced to 4 but should have been reduced
almost in proportion to the reduction of mantissa bits.
2005-10-08 22:43:55 +00:00
Bruce Evans
0b42281ee9 Fixed aliasing bugs in TRUNC() by using the fdlibm macros for access
to doubles as bits.  fdlibm-1.1 had similar aliasing bugs, but these
were fixed by NetBSD or Cygnus before a modified version of fdlibm was
imported in 1994.  TRUNC() is only used by tgamma() and some
implementation-detail functions.  The aliasing bugs were detected by
compiling with gcc -O2 but don't seem to have broken tgamma() on i386's
or amd64's.  They broke my modified version of tgamma().

Moved the definition of TRUNC() to mathimpl.h so that it can be fixed
in one place, although the general version is even slower than necessary
because it has to operate on pointers to volatiles to handle its arg
sometimes being volatile.  Inefficiency of the fdlibm macros slows
down libm generally, and tgamma() is a relatively unimportant part of
libm.  The macros act as if on 32-bit words in memory, so they are
hard to optimize to direct actions on 64-bit double registers for
(non-i386) machines where this is possible.  The optimization is too
hard for gcc on amd64's, and declaring variables as volatile makes it
impossible.
2005-09-19 11:28:19 +00:00
David Schultz
26bd283f2a Add a missing ldexpf() alias for amd64.
Noticed by:	bz@, tjr@
2005-09-12 20:54:00 +00:00
Ken Smith
a84020c2b9 Bump the shared library version number of all libraries that have not
been bumped since RELENG_5.

Reviewed by:	ru
Approved by:	re (not needed for commit check but in principle...)
2005-07-22 17:19:05 +00:00
Ruslan Ermilov
01293bdb90 Markup nit.
Approved by:	re (blanket)
2005-06-16 21:56:03 +00:00
Ruslan Ermilov
70db9cd000 Fixed compile warning.
Approved by:	re (blanket)
2005-06-16 21:55:45 +00:00
Ruslan Ermilov
f789cb8293 Assorted markup fixes.
Approved by:	re
2005-06-15 19:04:04 +00:00
Daniel Eischen
7f8fa2cf47 Prevent these functions from using stack outside of their frame.
Reported by:	Marc Olzheim <marcolz at stack dot nl>
OK'd by:	das
2005-05-06 15:44:20 +00:00
Stefan Farfeleder
66116c07a7 Revert the last change, the conversion from long double to double can raise
unwanted underflow exceptions.

Pointed out by:	das
2005-04-28 19:45:55 +00:00
Stefan Farfeleder
8f58ab910f Use double additions to raise the inexact exception to work around problems
with long double addition on sparc64.
2005-04-22 09:57:55 +00:00
Stefan Farfeleder
9eb30792de Fix raising the inexact exception (FE_INEXACT) if the result differs from the
argument.

Noticed by:	das
2005-04-22 08:30:33 +00:00
Andrey A. Chernov
db7354df52 Fix truncl.3 MLINKS 2005-04-17 19:57:52 +00:00
David Schultz
a4ca7ca8ac More optimized math functions. 2005-04-16 21:12:55 +00:00
David Schultz
2f2ee27de4 Implement truncl() based on floorl(). 2005-04-16 21:12:47 +00:00
David Schultz
07f3bc5b9c Add roundl(), lroundl(), and llroundl(). 2005-04-08 01:24:08 +00:00
David Schultz
4bb190a74b These files should include s_lround.c instead of s_lrint.c.
This only matters for efficiency, not for correctness.
2005-04-08 00:52:27 +00:00
David Schultz
fc87986708 Fix a (coincidentally harmless) bug. 2005-04-08 00:52:16 +00:00
David Schultz
46691dfbe7 Fix a long-standing bug in k_rem_pio2(), which led to large errors when
tanf() was called with big arguments close to multiples of pi/2.

Reported by:	ucbtest via bde
2005-04-05 23:27:47 +00:00
David Schultz
d06a0070af Build exp2(), exp2f(), and related documentation. 2005-04-05 02:57:39 +00:00
David Schultz
90232fdf16 Document exp2() and exp2f(), and make other minor tweaks and updates. 2005-04-05 02:57:28 +00:00
David Schultz
f8d6ede6b5 Implement exp2() and exp2f(). 2005-04-05 02:57:15 +00:00
David Schultz
3b9141ee91 Implement and document remquo() and remquof(). 2005-03-25 04:40:44 +00:00
David Schultz
2c2435825a Fix the double rounding problem with subnormals, and
remove the XXX comments, which no longer apply.
2005-03-18 02:27:59 +00:00
David Schultz
21122bea01 Add missing prototypes for fma() and fmaf(), and remove an inaccurate
comment.
2005-03-18 01:47:42 +00:00
David Schultz
9233b45ad9 Make the fenv.h routines work for programs that use SSE for
floating-point arithmetic on i386.  Now I'm going to make excuses
for why this code is kinda scary:

- To avoid breaking the ABI with 5.3-RELEASE, we can't change
  sizeof(fenv_t).  I stuck the saved mxcsr in some discontiguous
  reserved bits in the existing structure.

- Attempting to access the mxcsr on older processors results
  in an illegal instruction exception, so support for SSE must
  be detected at runtime.  (The extra baggage is optimized away
  if either the application or libm is compiled with -msse{,2}.)

I didn't run tests to ensure that this doesn't SIGILL on older 486's
lacking the cpuid instruction or on other processors lacking SSE.
Results from running the fenv regression test on these processors
would be appreciated.  (You'll need to compile the test with
-DNO_STRICT_DFL_ENV.)  If you have an 80386, or if your processor
supports SSE but the kernel didn't enable it, then you're probably out
of luck.

Also, I un-inlined some of the functions that grew larger as a result
of this change, moving them from fenv.h to fenv.c.
2005-03-17 22:21:46 +00:00
David Schultz
56ad27535a Spell 'fedisableexcept' correctly. 2005-03-16 22:34:14 +00:00
David Schultz
2e5fb44003 Document feenableexcept(), fedisableexcept(), and fegetexcept(). 2005-03-16 19:04:28 +00:00
David Schultz
10b01832c3 Replace fegetmask() and fesetmask() with feenableexcept(),
fedisableexcept(), and fegetexcept().  These two sets of routines
provide the same functionality.  I implemented the former as an
undocumented internal interface to make the regression test easier to
write.  However, fe(enable|disable|get)except() is already part of
glibc, and I would like to avoid gratuitous differences.  The only
major flaw in the glibc API is that there's no good way to report
errors on processors that don't support all the unmasked exceptions.
2005-03-16 19:03:46 +00:00
David Schultz
3d266bde6d Replace strong references with weak references. There's no
particularly good reason to do this, except that __strong_reference
does type checking, whereas __weak_reference does not.
On Alpha, the compiler won't accept a 'long double' parameter in
place of a 'double' parameter even thought the two types are
identical.
2005-03-07 21:27:37 +00:00
Stefan Farfeleder
3ddc6e9440 Remove an obsolete sentence from a comment. 2005-03-07 20:28:26 +00:00
David Schultz
c8642491d5 - If z is 0, one of x or y is 0, and the other is infinite, raise
an invalid exception and return an NaN.
- If a long double has 113 bits of precision, implement fma in terms
  of simple long double arithmetic instead of complicated double arithmetic.
- If a long double is the same as a double, alias fma as fmal.
2005-03-07 05:02:09 +00:00
David Schultz
388bf3b630 Document scalbnl and scalblnl. 2005-03-07 05:00:44 +00:00
David Schultz
6af2c5a60c Document nextafterl and nexttoward{,f,l}. 2005-03-07 05:00:29 +00:00
David Schultz
15a53f77fd Add nexttoward to the list of implemented functions, and explicitly
list the four that are still missing.
2005-03-07 04:59:53 +00:00
David Schultz
66d672d8cb Document fmal. 2005-03-07 04:59:43 +00:00
David Schultz
94e03502dc Remove ldexp and ldexpf. The former is in libc, and the latter is
identical to scalbnf, which is now aliased as ldexpf.  Note that the
old implementations made the mistake of setting errno and were the
only libm routines to do so.
2005-03-07 04:59:30 +00:00
David Schultz
aeb5e711f3 - Remove s_ldexpf.c (now aliased to scalbn.)
- Add nexttoward{,f,l} and nextafterl.  On all platforms,
  nexttowardl is an alias for nextafterl.
- Add fmal.
- Add man pages for new routines: fmal, nextafterl,
  nexttoward{,f,l}, scalb{,l}nl.

Note that on platforms where long double is the same as double, we
generally just alias the double versions of the routines, since doing
so avoids extra work on the source code level and redundant code in
the binary.  In particular:

		ldbl53		ldbl64/113
fmal       	s_fma.c		s_fmal.c
ldexpl     	s_scalbn.c	s_scalbnl.c
nextafterl 	s_nextafter.c	s_nextafterl.c
nexttoward 	s_nextafter.c	s_nexttoward.c
nexttowardf	s_nexttowardf.c	s_nexttowardf.c
nexttowardl	s_nextafter.c	s_nextafterl.c
scalbnl    	s_scalbn.c	s_scalbnl.c
2005-03-07 04:59:11 +00:00
David Schultz
228ad57d05 - Define FP_FAST_FMA for sparc64, since fma() is now implemented using
sparc64's 128-bit long doubles.
- Define FP_FAST_FMAL for ia64.
- Prototypes for fmal, frexpl, ldexpl, nextafterl, nexttoward{,f,l},
  scalblnl, and scalbnl.
2005-03-07 04:58:43 +00:00
David Schultz
beed720c37 Alias scalbn as ldexpl and scalbnl on platforms where long double is
the same as double.
2005-03-07 04:58:03 +00:00
David Schultz
7b6a19039d - Implement scalblnl.
- In scalbln and scalblnf, check the bounds of the second argument.
  This is probably unnecessary, but strictly speaking, we should
  report an error if someone tries to compute scalbln(x, INT_MAX + 1ll).
2005-03-07 04:57:50 +00:00
David Schultz
caacab9b5f Implement nexttowardf. This is used on both platforms with 11-bit
exponents and platforms with 15-bit exponents for long doubles.
2005-03-07 04:57:38 +00:00
David Schultz
ef94de735a Implement nexttoward and nextafterl; the latter is also known as
nexttowardl.  These are not needed on machines where long doubles
look like IEEE-754 doubles, so the implementation only supports
the usual long double formats with 15-bit exponents.

Anything bizarre, such as machines where floating-point and integer
data have different endianness, will cause problems.  This is the case
with big endian ia64 according to libc/ia64/_fpmath.h.  Please contact
me if you managed to get a machine running this way.
2005-03-07 04:56:46 +00:00
David Schultz
a506506a1c - Try harder to trick gcc into not optimizing away statements
that are intended to raise underflow and inexact exceptions.
- On systems where long double is the same as double, nextafter
  should be aliased as nexttoward, nexttowardl, and nextafterl.
2005-03-07 04:55:58 +00:00