Commit Graph

513 Commits

Author SHA1 Message Date
Steve Kargl
3fbe079a34 Remove whitespace and 2 blank lines. 2014-10-02 23:08:36 +00:00
Steve Kargl
dde47d8bbc * Whitespace. 2014-09-25 22:15:10 +00:00
Steve Kargl
f382031d34 For targets that have a signed zero, lgamma_r(-0, &signgamp) should
set signgamp = -1.

Submitted by:	enh at google dot com (e_lgamma[f]_r.c)
2014-09-17 19:01:22 +00:00
Steve Kargl
f7efd14df1 * Makefile:
. Hook e_lgammal[_r].c to the build.
  . Create man page links for lgammal[-r].3.

* Symbol.map:
  . Sort lgammal to its rightful place.
  . Add FBSD_1.4 section for the new lgamal_r symbol.

* ld128/e_lgammal_r.c:
  . 128-bit implementataion of lgammal_r().

* ld80/e_lgammal_r.c:
  . Intel 80-bit format implementation of lgammal_r().

* src/e_lgamma.c:
  . Expose lgammal as a weak reference to lgamma for platforms
    where long double is mapped to double.

* src/e_lgamma_r.c:
  . Use integer literal constants instead of real literal constants.
    Let compiler(s) do the job of conversion to the appropriate type.
  . Expose lgammal_r as a weak reference to lgamma_r for platforms
    where long double is mapped to double.

* src/e_lgammaf_r.c:
  . Fixed the Cygnus Support conversion of e_lgamma_r.c to float.
    This includes the generation of new polynomial and rational
    approximations with fewer terms.  For each approximation, include
    a comment on an estimate of the accuracy over the relevant domain.
  . Use integer literal constants instead of real literal constants.
    Let compiler(s) do the job of conversion to the appropriate type.
    This allows the removal of several explicit casts of double values
    to float.

* src/e_lgammal.c:
  . Wrapper for lgammal() about lgammal_r().

* src/imprecise.c:
  . Remove the lgamma.

* src/math.h:
  . Add a prototype for lgammal_r().

* man/lgamma.3:
  . Document the new functions.

Reviewed by:	bde
2014-09-15 23:21:57 +00:00
Steve Kargl
e85326216f Remove an initialized, but otherwise, unused variable. 2014-09-04 23:50:05 +00:00
Steve Kargl
733331540a According to the ISO C standard, lgamma(-integer) returns
inf and raises the divided-by-zero exception.  Compilers
constant fold one/zero to inf but do not raise the exception.
Introduce a volatile vzero to prevent the constant folding.

Move the declaration of zero into the main declaration block.

While here, fix a nearby disordering of 'lx,ix'

Discussed with:	bde
2014-09-01 18:57:13 +00:00
Steve Kargl
e63062b5bf Fix a tab that somehow became 8 spaces.
Remove parentheses in a return statement to be consistent with the
rest of the file.

Rename sin_pi() in the float version to sin_pif().

Remove large comment that precedes sin_pif().  The comment
duplicates a comment in e_lgamma_r.c where the algorithm
is documented.

Requested by:	bde
2014-09-01 16:24:25 +00:00
Steve Kargl
795b92049d Compute sin(pi*x) without actually doing the pi*x multiplication.
sin_pi(x) is only called for x < 0 and |x| < 2**(p-1) where p is
the precision of x.  The new argument reduction is an optimization
compared to the old code, and it removes a chunk of dead code.
Accuracy tests in the intervals (-21,-20), (-20,-19), ... (-1,0)
show no differences between the old and new code.

Obtained from:	bde
2014-08-31 21:38:03 +00:00
Steve Kargl
53c7f22849 Fix the order of "const volatile" to be consistent with
the rest of msun.
2014-08-30 17:31:53 +00:00
Steve Kargl
79c2e69a3f Make tiny volatile to prevent the compiler(s) from
constant folding expressions of the form "1 - tiny",
which are used to raise FE_INEXACT.
2014-08-30 17:14:47 +00:00
Steve Kargl
55ad7cd740 When r255294 was committed, it exposed the symbols lgammal, powl,
and tgammal in libm.  These functions are part of ISO/IEC 9899:1999
and their prototypes should have been moved into the appropriate
__ISO_C_VISIBLE >= 1999 section.  After moving the prototypes,
remnants of r236148 can be removed.

PR:		standards/191754
Reviewed by:	bde
2014-08-09 15:53:40 +00:00
Steve Kargl
d781108453 * Update the comments to agree with commit r226595.
* While here, fix a nearby typo in a comment.
2014-07-13 23:10:39 +00:00
Steve Kargl
3b5e0d0f96 * Makefile:
. Add s_erfl.c to building libm.
  . Add MLINKS for erfl.3 and erfcl.3.

* Symbol.map:
  . Move erfl and erfcl to their proper location.

* ld128/s_erfl.c:
  . Implementations of erfl and erfcl in the IEEE 754 128-bit format.

* ld80/s_erfl.c:
  . Implementations of erfl and erfcl in the Intel 80-bit format.

* man/erf.3:
  . Document the new functions.
  . While here, remove an incomplete sentence.

* src/imprecise.c:
  . Remove the stupidity of mapping erfl and erfcl to erf and erfc.

* src/math.h:
  . Move the declarations of erfl and erfcl to their proper place.

* src/s_erf.c:
  . For architectures where double and long double are the same
    floating point format, use weak references to map erfl to
    erf and ercl to erfc.

Reviewed by:	bde (many earlier versions)
2014-07-13 17:05:03 +00:00
Steve Kargl
7e1c60ae94 * Use 9 digits instead of 11 digits in efx and efx8.
* Update the domain and range of comments for the polynomial
  approximations, including using the the correct variable names
  (e.g., pp(x) instead of p(x)).

* Use hex values of the form 0x3e0375d4 instead of 0x1.06eba8p-3,
  which was obtained from printf("%.6a").

* In the domain [0.84375, 1.25], qa(x) can be reduced from a 4th
  order polynomial to 3rd order.

* In the domain [1.25,1/0.35], sa(x) can be reduced from a 4th
  order polynomial to 3rd order.

* In the domain [1/0.35, 11], the 4th order polynomials rb(x) and
  sb(x) can be reduced to 2nd and 3rd order, respectively.
2014-07-13 16:24:16 +00:00
Steve Kargl
c9cb48ff4d * Update the comments that refer to erf[c](nan) and erf[c](+-inf)
to use erf[c]f.
2014-07-13 16:05:33 +00:00
Steve Kargl
019ffb5df8 * Use the volatile qualifier for 'tiny' to prevent compilers
from erronously constant folding expressions of the form
  '1 - tiny'.  This allows erf[f](x) to raise INEXACT.

* Use 0.5, 1, and 2, which are exactly representable in radix-2
  floating point formats.  This reduces diffs between s_erf[fl].c.

* While here, add a comment about efx and efx8.
2014-07-13 15:45:45 +00:00
Steve Kargl
f2c0cd942c Whitespace. 2014-07-13 15:15:51 +00:00
Marcel Moolenaar
e7d939bda2 Remove ia64.
This includes:
o   All directories named *ia64*
o   All files named *ia64*
o   All ia64-specific code guarded by __ia64__
o   All ia64-specific makefile logic
o   Mention of ia64 in comments and documentation

This excludes:
o   Everything under contrib/
o   Everything under crypto/
o   sys/xen/interface
o   sys/sys/elf_common.h

Discussed at: BSDcan
2014-07-07 00:27:09 +00:00
Andrew Turner
cd82739201 Use __fenv_static for all static inline functions. 2014-01-25 16:03:08 +00:00
Steve Kargl
1531aa5f6a * msun/man/cosh.3:
* msun/man/sinh.3:
* msun/man/tanh.3:
  . Fix grammar.

* msun/src/e_coshl.c:
* msun/src/e_sinhl.c:
  . Fix comment.

* msun/src/s_tanhl.c:
  . Remove unused variables.
  . Fix location/indentation of comments.
  . Use comparison involving ints instead of long double.
  . Re-order polynomial evaluation on ld128 for |x| < 0.25.
    For now, retain the older order in an "#if 0 ... #else" block.
  . Use int comparison to short-circuit the |x| < 1.5 condition.

Requested by:	bde
2013-12-31 23:59:33 +00:00
Steve Kargl
a48e1f224c * Makefile:
. Hook coshl, sinhl, and tanhl into libm.
  . Create symbolic links for corresponding manpages.
  . While here remove a nearby extraneous space.

* Symbol.map:
* src/math.h:
  . Move coshl, sinhl, and tanhl to their proper locations.

* man/cosh.3:
* man/sinh.3:
* man/tanh.3:
  . Update the manpages.

* src/e_cosh.c:
* src/e_sinh.c:
* src/s_tanh.c:
  . Add weak reference for LBDL_MANT_DIG==53 targets.

* src/imprecise.c:
  . Remove the coshl, sinhl, and tanhl kludge.

* src/e_coshl.c:
  . ld80 and ld128 implementation of coshl().

* src/e_sinhl.c:
  . ld80 and ld128 implementation of sinhl().

* src/s_tanhl.c:
  . ld80 and ld128 implementation of tanhl().

Obtained from:	bde (mostly), das and kargl
2013-12-30 01:06:21 +00:00
Steve Kargl
30a919dde7 Yet, another attempt to fix the libm breakage due to the
changes in s_roundl.c to use bit twiddling.

Reported by:	ian
2013-11-07 22:46:13 +00:00
Steve Kargl
0e9dcedc67 Fix bulding libm on platforms with LDBL_MANT_DIG == 53.
Reported by:	ian
2013-11-07 21:20:34 +00:00
Steve Kargl
db89cf8efb * Use "math.h" instead of <math.h>.
* Use bit twiddling.  This requires inclusion of math_private.h
  and inclusion of float.h in s_roundl.c.  Raise invalid exception.
* Use literal integer constants where possible.  Let the compiler
  do the appropriate conversion.
* In s_roundf.c, use an F suffix on float constants instead of
  promoting float to double and then converting the result back
  to float. In s_roundl.c, use an L suffix.
* In s_roundl.c, use the ENTERI and RETURNI macros.  This requires
  the inclusion of fpmath.h and on __i386__ class hardware ieeefp.h.

Reviewed by:	bde
2013-11-06 23:44:52 +00:00
Andrew Turner
0a10f22a30 On ARM EABI double precision floating point values are stored in the
endian the CPU is in, i.e. little-endian on most ARM cores.

This allows ARMv4 and ARMv5 boards to boot with the ARM EABI.
2013-09-07 14:04:10 +00:00
David Chisnall
4758b87596 Add stub implementations of the missing C++11 math functions.
These are weak and so can be replaced by other versions in applications
that choose to do so, and will give a linker warning when used so that
applications that rely on the extra precision can avoid them.

Note that since the C/C++ specs only guarantee that long double has
precision equal to double, code that actually relies on these functions
having greater precision is unportable at best and broken at worst.
2013-09-06 07:58:23 +00:00
Steve Kargl
e826e6be2b * Whitespace. 2013-08-28 16:59:55 +00:00
Steve Kargl
2a3910b931 * s_erf.c:
. Use integer literal constants instead of double literal constants.

* s_erff.c:
  . Use integer literal constants instead of casting double literal
    constants to float.
  . Update the threshold values from those carried over from erf() to
    values appropriate for float.
  . New sets of polynomial coefficients for the rational approximations.
    These coefficients have little, but positive, effect on the maximum
    error in ULP in the four intervals, but do improve the overall
    speed of execution.
  . Remove redundant GET_FLOAT_WORD(ix,x) as hx already contained the
    contents that is packed into ix.
  . Update the mask that is used to zero-out lower-order bits in x in
    the intervals [1.25, 2.857143] and [2.857143, 12].  In tests on
    amd64, this change improves the maximum error in ULP from 6.27739
    and 63.8095 to 3.16774 and 2.92095 on these intervals for erffc().

Reviewed by:	bde
2013-08-27 19:46:56 +00:00
David Chisnall
fb69d6083d Restore the longer form of the _Generic. The short form does not work in C++. 2013-07-29 12:33:03 +00:00
David Chisnall
6b69e627a8 Reenable the isnan(double) / isinf(double) declarations when targeting C89 + SUSv2 mode. 2013-07-29 08:32:13 +00:00
David Chisnall
b8f19c9247 Cleaner support for type qualifiers.
Submitted by:	Pasi Parviainen
2013-07-13 13:04:38 +00:00
David Chisnall
e21be487d3 Ensure that the _Generic() macro in math.h works with qualified types.
tgmath.h contains the same bugs and so should be fixed in the same way.
2013-07-13 10:10:45 +00:00
David Chisnall
1583bcb4ee Fix the build with C++ where __builtin_types_compatible_p is not allowed. 2013-07-12 11:03:51 +00:00
David Chisnall
95f82796a9 Fix some typoes in math.h cleanup. 2013-07-11 19:34:16 +00:00
David Chisnall
a3fc79de87 Cleanups to math.h that prevent namespace conflicts with C++.
Reviewed by:	bde
MFC after:	3 days
2013-07-11 17:41:04 +00:00
Eitan Adler
19eb5fb06b Make the order of operations for lib/msun more clear.
Tested with md5 sum of object code

Reported by:	swildner@DragonFlyBSD.org
Submitted by:	bde
2013-06-24 19:12:17 +00:00
David Schultz
998b640bcb Add implementations of acoshl(), asinhl(), and atanhl(). This is a
merge of the work done by bde and myself.
2013-06-10 06:04:58 +00:00
David Schultz
0b8d0b5be9 Style fixes.
Submitted by:	bde
2013-06-05 05:33:01 +00:00
Steve Kargl
3ffff4bad5 ld80 and ld128 implementations of expm1l(). This code started life
as a fairly faithful implementation of the algorithm found in

PTP Tang, "Table-driven implementation of the Expm1 function
in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 18,
211-222 (1992).

Over the last 18-24 months, the code has under gone significant
optimization and testing.

Reviewed by:	bde
Obtained from:	bde (most of the optimizations)
2013-06-03 19:51:32 +00:00
David Schultz
25a4d6bfda Add logl, log2l, log10l, and log1pl.
Submitted by:	bde
2013-06-03 09:14:31 +00:00
David Schultz
e4afa19c33 I'm happy to finally commit stephen@'s implementations of cacos,
cacosh, casin, casinh, catan, and catanh. Thanks to stephen@ and bde@
for working on these.

Submitted by:	stephen@
Reviewed by:	bde
2013-05-30 04:49:26 +00:00
David Schultz
7dbbb6dde3 Fix some regressions caused by the switch from gcc to clang. The fixes
are workarounds for various symptoms of the problem described in clang
bugs 3929, 8100, 8241, 10409, and 12958.

The regression tests did their job: they failed, someone brought it
up on the mailing lists, and then the issue got ignored for 6 months.
Oops. There may still be some regressions for functions we don't have
test coverage for yet.
2013-05-27 08:50:10 +00:00
Dimitry Andric
0779690c2e Only define isnan, isnanf, __isnan and __isnanf in libc.so, not in
libc.a and libc_p.a.  In addition, define isnan in libm.a and libm_p.a,
but not in libm.so.

This makes it possible to statically link executables using both isnan
and isnanf with libc and libm.

Tested by:	kargl
MFC after:	1 week
2012-11-10 21:22:10 +00:00
Kevin Lo
0f5e7edc14 Fix typo; s/ouput/output 2012-11-07 07:00:59 +00:00
Warner Losh
98fd12e162 Revert r241756 2012-10-22 13:21:11 +00:00
Warner Losh
b3f94d242f Revert r241755 2012-10-22 13:20:31 +00:00
Warner Losh
527a7c56f7 Document the method used to compute expf. Taken from exp, with
changes to reflect differences in computation between the two.
2012-10-19 22:47:44 +00:00
Warner Losh
aa616aa22d Document the methods used to compute logf. Taken and edited from the
double version, with adaptations for the differences between it and
the float version.
2012-10-19 22:46:48 +00:00
Steve Kargl
a077586c53 * src/math_private.h:
. Change the API for the LD80C by removing the explicit passing
    of the sign bit.  The sign can be determined from the last
    parameter of the macro.
  . On i386, load long double by bit manipulations to work around
    at least a gcc compiler issue.  On non-i386 ld80 architectures,
    use a simple assignment.

* ld80/s_expl.c:
  . Update the only consumer of LD80C.

Submitted by:	bde
Approved by:	das (mentor)
2012-09-29 16:40:12 +00:00
Steve Kargl
340076f0f6 * Use ENTERI() and RETURNI() to toggle the rounding precision if
necessary, so that cosl(), sinl() and tanl() work on i386 even
  for naive callers.

Suggested by:	bde
Reviewed by:	bde
Approved by: 	das (mentor)
2012-09-22 15:38:29 +00:00
Steve Kargl
e6f9129aa0 * Make STRICT_ALIGN() work for doubles as well as for floats. This
only affects i386.  The double case was intentionally left broken
  as an optimization, but we are getting closer to supporting
  applications and/or kernels that change the (FreeBSD i386) default
  rounding precision from FP_PD to FP_PE and never change it back,
  and this requires the STRICT_ALIGN()s that were added to support
  FP_PE to actually work in all precisions.

* Remove an extraneous semicolon at the end of a macro that was
  supposed to be function-like.

Submitted by:	bde
Approved by:	das (mentor)
2012-09-22 15:19:11 +00:00
Dimitry Andric
f049a6cb4a Add __always_inline to __ieee754_rem_pio2() and __ieee754_rem_pio2f(),
since some older versions of gcc refuse to inline these otherwise.

Requested by:	bde
MFC after:	1 week
2012-08-11 15:47:22 +00:00
Dimitry Andric
2b795b2921 Change a few extern inline functions in libm to static inline, since
they need to refer to static constants, which C99 does not allow for
extern inline functions.

While here, change a comment in e_rem_pio2f.c to mention the correct
number of bits.

Reviewed by:	bde
MFC after:	1 week
2012-08-11 11:13:48 +00:00
Steve Kargl
82b89f4850 ieeefp.h is only needed on i386 class hardware.
Submitted by:	bde
Approved by:	das (pre-approved)
2012-07-30 21:58:28 +00:00
Steve Kargl
ca50c4b871 Whitespace.
Submitted by:	bde
Approved by:	das (pre-approved)
2012-07-30 21:55:49 +00:00
Steve Kargl
3458a81e65 Replace code that toggles between 53 and 64 bits on i386
class hardware with the ENTERI and RETURNI macros, which
are now available in math_private.h.

Suggested by:	bde
Approved by: das (mentor)
2012-07-26 03:50:24 +00:00
Steve Kargl
b83ccea32c Compute the exponential of x for Intel 80-bit format and IEEE 128-bit
format.  These implementations are based on

PTP Tang, "Table-driven implementation of the exponential function
in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 15,
144-157 (1989).

PR: standards/152415
Submitted by: kargl
Reviewed by: bde, das
Approved by: das (mentor)
2012-07-23 19:13:55 +00:00
David Chisnall
8f62d384b9 Allow inclusion of libc++ <cmath> to work after including math.h
Submitted by:	Yamaya Takashi
Reviewed by:	das
MFC after:	1 week
2012-05-27 12:54:41 +00:00
Dag-Erling Smørgrav
084f679591 I stopped using my middle name years ago. 2012-04-25 18:07:35 +00:00
David Schultz
1cbd288942 Fix a bug in remquo{,f,l}, in which the quotient didn't always have the
correct sign when the remainder was 0.

Fix a separate bug in remquo alone, in which the remainder and
quotient were both off by a bit in certain cases involving subnormal
remainders.

The bugs affected all platforms except amd64 and i386, on which the
routines are implemented in assembly.

PR:		166463
Submitted by:	Ilya Burylov
MFC after:	2 weeks
2012-04-07 03:59:12 +00:00
David Schultz
6e3ab4e1b3 Fix a small nit noted by bde: exp_x should be of type float, not double. 2012-01-20 07:02:42 +00:00
David Schultz
7bde21b1f9 Add an implementation of fenv.h intended for platforms that lack an FPU and
use softfloat.

Thanks to Ian Lepore for testing and debugging this patch.  The fenv
regression tests pass (at least for Ian's arm chip) with this change.
2012-01-16 04:09:17 +00:00
Ulrich Spörlein
bf3f9db657 Convert files to UTF-8 and add some copyright markers where missing. 2012-01-07 16:13:56 +00:00
David Chisnall
e481b86384 Expose the unimplemented libm functions in the math.h header. This allows C++'s <cmath> to work without the compiler complaining that the C++ versions are calling implicitly-declared functions. You will still get a linker error when they are called. OpenBSD 5.0 claims to fully implement the C99 <math.h> stuff, so might be worth investigating...
Reviewed by:	das
Approved by:	dim (mentor)
2011-11-12 19:55:48 +00:00
David Schultz
0c7e4d5fc1 Fix a regression introduced in r226371: When the high part of x*y
exactly cancels with z, return the low part of x*y instead of
discarding it.
2011-10-21 06:30:43 +00:00
David Schultz
bc23acdc32 Fix a corner case: tan(large + Inf i) == NaN + NaN i. 2011-10-21 06:30:16 +00:00
David Schultz
c6df46bafb Improved handling of large x in ccosh{,f}():
- Handle cases where exp(x) would overflow, but ccosh(x) ~= exp(x) / 2
  shouldn't.
- Use the ccosh(x) ~= exp(x) / 2 approximation to simplify the calculation
  when x is large.

Similarly for csinh().  Also fixed the return value of csinh(-Inf +- 0i).
2011-10-21 06:29:32 +00:00
David Schultz
d4657ac799 Use __ldexp_exp() to simplify things and improve accuracy for x near
the overflow threshold.
2011-10-21 06:28:47 +00:00
David Schultz
12188b77a2 The cexp() and {,c}{cos,sin}h functions all need to be able to compute
exp(x) scaled down by some factor, and the challenge is doing this
accurately when exp(x) would overflow.  This change replaces all of
the tricks we've been using with common __ldexp_exp() and
__ldexp_cexp() routines that handle all the scaling.

bde plans to improve on this further by moving the guts of exp() into
k_exp.c and handling the scaling in a more direct manner.  But the
current approach is simple and adequate for now.
2011-10-21 06:27:56 +00:00
David Schultz
f2ea2b9d27 Use STRICT_ASSIGN() to ensure that the compiler doesn't screw things
up by storing x in a wider type than it's supposed to.

Submitted by:	bde
2011-10-21 06:26:38 +00:00
David Schultz
cd24d79843 Per IEEE754r, pow(1, y) is 1 even if y is NaN, and pow(-1, +-Inf) is 1.
MFC after:	2 weeks
2011-10-21 06:26:07 +00:00
David Schultz
3daee1d6c3 Add c{cos,sin,tan}{,h}{,f} functions. This is joint work with
bde and kargl.
2011-10-17 05:41:03 +00:00
David Schultz
4ce31585dc Optimize the case of pure imaginary arguments. Calls like this are
common, e.g., in DFT implementations.

Discussed with:	bde, kargl
2011-10-16 05:37:01 +00:00
David Schultz
e62394861d Move the macros GET_LDBL_EXPSIGN() and SET_LDBL_EXPSIGN() into
math_private.h, so they can be used elsewhere in the math library.
2011-10-16 05:36:39 +00:00
David Schultz
eccf8b3a30 Remove an unused variable. 2011-10-16 05:36:23 +00:00
David Schultz
e595c01fd8 Remove some unnecessary initializations.
Obtained from:	DragonFlyBSD
2011-10-15 07:00:28 +00:00
David Schultz
b052ec9065 Various changes to improve the accuracy and speed of log{2,10}{,f}.
- Rename __kernel_log() to k_log1p().
- Move some of the work that was previously done in the kernel log into
  the callers.  This enables further refactoring to improve accuracy or
  speed, although I don't recall the details.
- Use extra precision when adding the final scaling term, which improves
  accuracy.
- Describe and work around compiler problems that break some of the
  multiprecision calculations.

A fix for a small bug is also included:
- Add a special case for log*(1).  This is needed to ensure that log*(1) == +0
  instead of -0, even when the rounding mode is FE_DOWNWARD.

Submitted by:	bde
2011-10-15 05:23:28 +00:00
David Schultz
5ebf26f6a1 Style fixes and updates to comments.
Submitted by:	bde
2011-10-15 05:00:56 +00:00
David Schultz
15d5d9deb1 Don't define FP_FAST_FMA on sparc64; with the recent fixes, fma() is
no longer "fast" on sparc64.  (It really wasn't to begin with, since
the old implementation was using long doubles, and long doubles are
emulated in software on sparc64.)
2011-10-15 04:24:54 +00:00
David Schultz
3d4dfde48a Add INSERT_WORD64 and EXTRACT_WORD64 macros for use in s_fma.c. 2011-10-15 04:22:55 +00:00
David Schultz
ec95083025 Fix a double-rounding bug in fma{,f,l}. The bug would occur in
round-to-nearest mode when the result, rounded to twice machine
precision, was exactly halfway between two machine-precision
values.  The essence of the fix is to simulate a "sticky bit" in
the pathological cases, which is how hardware implementations
break the ties.

MFC after:	1 month
2011-10-15 04:16:58 +00:00
David Schultz
7792754061 Refactor this code by introducing separate functions to handle the
extra-precision add and multiply operations. This simplifies future
work but shouldn't result in any functional change.
2011-10-11 05:17:45 +00:00
Steve Kargl
edfca01f71 In the libm access macros for the double type, z can sometimes
be used uninitialized.  This can lead to spurious exceptions
and bit clobbering.

Submitted by:	bde
Approved by:	das (mentor)
2011-06-19 17:07:58 +00:00
Steve Kargl
9aa461b570 Clean up the unneeded cpp macro INLINE_REM_PIO2L.
Reviewed by:	das
Approved by:	das (mentor)
2011-05-30 19:41:28 +00:00
Steve Kargl
c273267e83 Improve the accuracy from a max ULP of ~2000 to max ULP < 0.79
on i386-class hardware for sinl and cosl.  The hand-rolled argument
reduction have been replaced by e_rem_pio2l() implementations.  To
preserve history the following commands have been executed:

svn cp src/e_rem_pio2.c ld80/e_rem_pio2l.h
mv ${HOME}/bde/ld80/e_rem_pio2l.c ld80/e_rem_pio2l.h

svn cp src/e_rem_pio2.c ld128/e_rem_pio2l.h
mv ${HOME}/bde/ld128/e_rem_pio2l.c ld128/e_rem_pio2l.h

The ld80 version has been tested by bde, das, and kargl over the
last few years (bde, das) and few months (kargl).  An older ld128
version was tested by das.  The committed version has only been
compiled tested via 'make universe'.

Approved by: das (mentor)
Obtained from: bde
2011-04-29 23:13:43 +00:00
Steve Kargl
1cd0ec03d6 Take two. Add the missing file that should have been committed
with r219571 and re-enable building of cbrtl.

Implement the long double version for the cube root function, cbrtl.
The algorithm uses Newton's iterations with a crude estimate of the
cube root to converge to a result.

Reviewed by:    bde
Approved by:    das
2011-03-12 19:37:35 +00:00
Steve Kargl
dfe5233b59 Implement the long double version for the cube root function, cbrtl.
The algorithm uses Newton's iterations with a crude estimate of the
cube root to converge to a result.

Reviewed by:	bde
Approved by:	das
2011-03-12 16:50:39 +00:00
David Schultz
97a539be1f Convert log10f() to use __kernel_log(), which is more accurate and simpler. 2011-03-07 03:12:08 +00:00
David Schultz
acda0929b2 Convert log10() to use __kernel_log(), which is more accurate and simpler. 2011-03-07 03:11:27 +00:00
David Schultz
f3732b5aaa Add cexp() and cexpf().
Reviewed by:	bde (earlier version)
2011-03-07 03:09:24 +00:00
Rebecca Cran
6bccea7c2b Fix typos - remove duplicate "the".
PR:	bin/154928
Submitted by:	Eitan Adler <lists at eitanadler.com>
MFC after: 	3 days
2011-02-21 09:01:34 +00:00
David Schultz
b5209b6228 Fix a bug where the wrong argument was passed to SET_FLOAT_WORD().
This bug results in a type mismatch that happens to be harmless
because of the way SET_FLOAT_WORD() works.

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

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

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

Reviewed by:	bde
2011-02-10 07:37:29 +00:00
David Schultz
f353f24867 Another minor nit: Make sure the constant here is a float so the compiler
doesn't promote the entire expression to double.
2010-12-07 03:29:36 +00:00
David Schultz
63687c8b08 Fix various nits in style and comments that were pointed out by bde.
Code changes verified with md5.
2010-12-07 02:19:15 +00:00
David Schultz
177668d11f Add log2() and log2f(). 2010-12-05 22:11:22 +00:00
David Schultz
e7780530fa Add a "kernel" log function, based on e_log.c, which is useful for
implementing accurate logarithms in different bases.  This is based
on an approach bde coded up years ago.

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

The kernel takes a reduced argument x and returns the same polynomial
approximation as e_log.c, but omitting the low-order term. The low-order
term is much larger than the rest of the approximation, so the caller of
the kernel function can scale it to the appropriate base in extra precision
and obtain a much more accurate answer than by using log(x)/log(b).
2010-12-05 22:11:03 +00:00
Ulrich Spörlein
e61ffaea2a Fix bug in jn(3) and jnf(3) that led to -inf results
Explanation by Steve:
jn[f](n,x) for certain ranges of x uses downward recursion to compute
the value of the function.  The recursion sequence that is generated is
proportional to the actual desired value, so a normalization step is
taken.  This normalization is j0[f](x) divided by the zeroth sequence
member.  As Bruce notes, near the zeros of j0[f](x) the computed value
can have giga-ULP inaccuracy. I found for the 1st zero of j0f(x) only
the leading decimal digit is correct.  The solution to the issue is
fairly straight forward.  The zeros of j0(x) and j1(x) never coincide,
so as j0(x) approaches a zero, the normalization constant switches to
j1[f](x) divided by the 2nd sequence member.  The expectation is that
j1[f](x) is a more accurately computed value.

PR:		bin/144306
Submitted by:	Steven G. Kargl <kargl@troutmask.apl.washington.edu>
Reviewed by:	bde
MFC after:	7 days
2010-11-13 10:54:10 +00:00
David Schultz
efd0f253c2 Introduce __isnanf() as an alias for isnanf(), and make the isnan()
macro expand to __isnanf() instead of isnanf() for float arguments.
This change is needed because isnanf() isn't declared in strict POSIX
or C99 mode.

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

Reported by:	Florian Forster <octo@verplant.org>
2010-06-12 17:32:05 +00:00
Ed Schouten
a4f326ddd5 Use the documented machine constraint for SSE registers.
The amd64-specific bits of msun use an undocumented constraint, which is
less likely to be supported by other compilers (such as Clang). Change
the code to use a more common machine constraint.

Obtained from:	/projects/clangbsd/
2009-06-11 13:59:51 +00:00
Ed Schouten
b492f2899f Use ISO C99 style inline semantics in msun.
Because we use ISO C99 nowadays, we can just get rid of enforcing
GNU89-style inlining.
2009-06-03 08:16:34 +00:00
David Schultz
fbaabc11ae Namespace: scalb() is withdrawn from POSIX. 2009-03-14 18:58:53 +00:00
David Schultz
24863729f9 Eliminate __real__ and __imag__ gccisms. 2009-03-14 18:24:15 +00:00
David Schultz
ea8e257984 C99 TC2 now wants FP_FAST_FMA* to be defined to 1, if the macros are
defined at all. See also: defect report #223.
2009-02-07 05:41:24 +00:00
David Schultz
4630140ce2 Use __gnu89_inline so that these files will compile with newer versions
of gcc, where the meaning of 'inline' was changed to match C99.

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

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

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

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

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

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

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

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

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

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

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

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

Reviewed by:			bde
sparc64 testing resources from:	remko
2008-07-31 22:41:26 +00:00
David Schultz
71da0e146b The high part of the mantissa is 64 bits on sparc64. 2008-07-31 20:09:47 +00:00
David Schultz
16608a810d As in other parts of libm, mark a few constants as volatile to prevent
spurious optimizations. gcc doesn't support FENV_ACCESS, so when it
folds constants, it assumes that the rounding mode is always the
default and floating point exceptions never matter.
2008-07-31 19:57:50 +00:00
David Schultz
f2dc0faad0 Implement fmodl.
Document fmodl and fix some errors in the fmod manpage.
2008-06-19 22:39:53 +00:00
David Schultz
92a1a6e169 Fix some corner cases:
- fma(x, y, z) returns z, not NaN, if z is infinite, x and y are finite,
  x*y overflows, and x*y and z have opposite signs.
- fma(x, y, z) doesn't generate an overflow, underflow, or inexact exception
  if z is NaN or infinite, as per IEEE 754R.
- If the rounding mode is set to FE_DOWNWARD, fma(1.0, 0.0, -0.0) is -0.0,
  not +0.0.
2008-04-03 06:14:51 +00:00
David Schultz
8087c515ab Remove a (bogus) remnant of debugging this on sparc64. 2008-03-31 13:11:45 +00:00
David Schultz
c7392feecc Hook remquol() and remainderl() up to the build. 2008-03-30 20:48:02 +00:00
David Schultz
a2e5f27559 Implement remainderl() as a wrapper around remquol(). The extra work
remquol() performs to compute the quotient is negligible.
2008-03-30 20:47:42 +00:00
David Schultz
cef56f9d6d Implement remquol() based on remquo(). 2008-03-30 20:47:26 +00:00
David Schultz
511dd36b32 Implement csqrtl(). 2008-03-30 20:07:15 +00:00
David Schultz
84c1c0a1ca Hook hypotl() and cabsl() up to the build. 2008-03-30 20:03:46 +00:00
David Schultz
a641fc76eb Alias hypotl() and cabsl() for platforms where long double is the same
as double.
2008-03-30 20:03:06 +00:00
David Schultz
2264157a42 Implement cabsl() in terms of hypotl().
Submitted by:	Steve Kargl <sgk@troutmask.apl.washington.edu>
2008-03-30 20:02:03 +00:00
David Schultz
d23166b015 Implement hypotl(). This is bde's conversion of fdlibm hypot(), with minor
fixes for ld128 by me.
2008-03-30 20:01:50 +00:00
Bruce Evans
42ee187c3c Use fabs[f]() instead of bit fiddling for setting absolute values.
This makes little difference in float precision, but in double
precision gives a speedup of about 30% on amd64 (A64 CPU) and i386
(A64).  This depends on fabs[f]() being inline and efficient.  The
bit fiddling (or any use of SET_HIGH_WORD(), which libm does too
much because it was best on old 32-bit machines) always causes
packing overheads and sometimes causes stalls in the packing, since
it operates on only part of a variable in the double precision case.
It apparently did cause stalls in a critical path here.
2008-03-30 18:07:12 +00:00
Bruce Evans
c0c7ddd3a8 Use the expression fabs(x+0.0)-fabs(y+0.0) instead of
fabs(x+0.0)+fabs(y+0.0) when mixing NaNs.  This improves
consistency of the result by making it harder for the compiler to reorder
the operands.  (FP addition is not necessarily commutative because the
order of operands makes a difference on some machines iff the operands are
both NaNs.)
2008-03-30 17:28:27 +00:00
Bruce Evans
f94997c8d7 Fix a missing mask in a hi+lo decomposition. Thus bug made the extra
precision in software useless, so hypotf() had some errors in the 1-2
ulp range unless there is extra precision in hardware (as happens on
i386).
2008-03-30 17:17:42 +00:00
David Schultz
a1af0d70da Include math.h for the fmaf() prototype. 2008-03-29 16:38:29 +00:00
David Schultz
ee0730e61e Fix some rather obscene code that has ambiguous if...if...else...
constructs in it.
2008-03-29 16:37:59 +00:00
David Schultz
c6a4447b64 MI implementation of sqrtl(). This is very slow and should
be overridden when hardware sqrt is available.
2008-03-02 01:47:58 +00:00
Bruce Evans
a278d99026 Fix and improve some magic numbers for the "medium size" case.
e_rem_pio2.c:
This case goes up to about 2**20pi/2, but the comment about it said that
it goes up to about 2**19pi/2.

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

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

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

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

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

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

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

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

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

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

e_rem_pio2f.c:
Float precision worked in practice because of a compensating off-by-1
error here.  Double precision was asked for, and was almost needed,
since the cosf() and sinf() callers want to produce extra-precision
results, at least internally so that their error is only 0.5009 ulps.
However, the extra precision provided by unbroken float precision is
enough, and the double-precision code has extra overheads, so the
off-by-1 error cost about 5% in efficiency on amd64 and i386.
2008-02-25 11:43:20 +00:00
Bruce Evans
60a50c2585 Optimize the 9pi/2 < |x| <= 2**19pi/2 case some more by avoiding an
fabs(), a conditional branch, and sign adjustments of 3 variables for
x < 0 when the branch is taken.  In double precision, even when the
branch is perfectly predicted, this saves about 10 cycles or 10% on
amd64 (A64) and i386 (A64) for the negative half of the range, but
makes little difference for the positive half of the range.  In float
precision, it also saves about 4 cycles for the positive half of the
range on i386, and many more cycles in both halves on amd64 (28 in the
negative half and 11 in the positive half for tanf), but the amd64
times for float precision are anomalously slow so the larger
improvement is only a side effect.

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

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

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

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

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

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

This is only for internal use.  The libm versions of *rint*() should
also be inline, but that would take would take more header engineering.
Implementing irint() instead of lrint() also avoids a conflict with
the extern declaration of the latter.
2008-02-22 14:11:03 +00:00
Bruce Evans
f839bac29c Optimize the conversion to bits a little (by about 11 cycles or 16%
on i386 (A64), 5 cycles on amd64 (A64), and 3 cycles on ia64).  gcc
tends to generate very bad code for accessing floating point values
as bits except when the integer accesses have the same width as the
floating point values, and direct accesses to bit-fields (as is common
only for long double precision) always gives such accesses.  Use the
expsign access method, which is good for 80-bit long doubles and
hopefully no worse for 128-bit long doubles.  Now the generated code
is less bad.  There is still unnecessary copying of the arg on amd64
and i386 and mysterious extra slowness on amd64.
2008-02-22 11:59:05 +00:00
Bruce Evans
a7aa8cc980 Optimize the fixup for +-0 by using better classification for this case
and by using a table lookup to avoid a branch when this case occurs.
On i386, this saves 1-4 cycles out of about 64 for non-large args.
2008-02-22 10:04:53 +00:00