On Tue, Sep 26, 2017 at 6:27 AM, Jan Stary <[email protected]> wrote:
> s_sin.c normalizes the argument to [-pi/4, +pi/4].
> This is how |x| <= pi/4 is tested:
> GET_HIGH_WORD(ix,x);
> ix &= 0x7fffffff;
> if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
>
> Why is it done like that? Is it faster or more portable
> or in any way better that comparing the value itself to M_PI_4?
>
See s_cos.c s_tan.c; and many others start with a similar block.
Probably the integer comparison is efficient (fewer average CPU and bus
resources per second tied up per operation). It will depend upon your
computer's characteristics, and applications running, and how many times
per second sin() is invoked on average.
Assuming the compiler optimization of the above code block is as good as it
could be:
that should hinge on whether a single integer copy, and 32-bit integer
subtraction
and Bitwise AND on your CPU will burn more processor work cycles than two
floating-point copy,
two floating-point subtraction plus one sign negate operation against
IEEE 64-bit double.
The basic rule of thumb says that if a performance-significant task can
be completed using Integers
instead, then maximum effort should be made to avoid/minimize unnecessary
usage of
floating-point operations (without an excessive increase in the # of
operations),
As 3 to 4 times the processor work cycles for execution path to
3-argument 64-bit floating point
calculation Versus the corresponding 3-argument operation using 32-bit
integers.
More floating point operations/sec = lower system efficiency, or
less-effective use of the overall available
compute capacity Versus the use of processors' regular, typically
more-optimized ALU pipelines.
> if (-M_PI_4 < x && x < M_PI_4)
> >For Inf and NaN arguments, NaN is returned as follows:
> > /* sin(Inf or NaN) is NaN */
> > else if (ix>=0x7ff00000) return x-x;
>
> > Again, why the integer conversion? Would
> >
> > else if (isinf(x) || isnan(x))
> Also, is "return x-x" just a fast/clever way to return NaN
>
Well, the original code is applying a >= test, whereas isinf() and
isnan() are
shown to be equality tests that check for two specific values of the
exponent field.
The || branching is involving more computations though....
General application code should use the new isinf(), isnan(), and
nan("") macros,
but they have not always been part of the C standard, and I imagine this
code predates it.
The NaN/InF values are runtime-specific in the current C standard, so
it is
only sort of legitimate to do that, Because this code is part of the
libc runtime's
implementation itself.....
In this context, the libc implementation has enough information to safely
rely
on the assumption to make the decision without resorting to a macro call
that
invokes a number of other operations, and so
Is free and perfectly fine to use that ix >= 0x7ff00000 to equate
to a NaN condition.
That appears to potentially streamline the number of computations required
for this case,
so there might actually be a performance benefit to not use the macros
here as well.
--
-JH