Complex arg-trig functions
Stephen Montgomery-Smith
stephen at missouri.edu
Sun Sep 16 19:01:40 UTC 2012
On 09/16/2012 11:51 AM, Bruce Evans wrote:
>
> I don't like that. It will be much slower on almost 1/4 of arg space.
> The only reason to consider not doing it is that the args that it
> applies to are not very likely, and optimizing for them may pessimize
> the usual case.
The pessimization when |z| is not small is tiny. It takes no time at
all to check that |z| is small.
On the other hand let me go through the code and see what happens when
|x| is small or |y| is small. There are actually specific formulas that
work well in these two cases, and they are probably not that much slower
than the formulas I decided to remove. And when you chase through all
the logic and "if" statements, you may find that you didn't use up a
whole bunch of time for these very special cases of |z| small - most of
the extra time merely being the decisions invoked by the "if" statements.
> I just found a related optimization for atan2(). For x > 0 and
> |y|/x < 2**-(MANT_DIG+afew), atan2(y, x) is evaluated as essentially
> sign(y) * atan(|y|/x). But in this case, its value is simply y/x
> with inexact. Again the optimization applies to almost 1/4 of arg
> space. It gains more than the normal overhead of an atan() call by
> avoiding secondary underflows when y/x underflows.
You see, that is exactly where I don't want to do special optimization
in my code. In my opinion, it is the tan function itself that should
realize that |y|/x is small, and hence it is that function that simply
return |y|/x. Or if you want to implement it at a higher level, atan2
should make this realization, and simply return y/x.
Similarly, I would expect log1p(x) to simply return x (inexactly) for x
small. And if the compiler is really good, I would hope that the two codes:
log1p(x);
(fabs(x) < DBL_EPSILON) ? x + set_tiny() : log1p(x);
would be equivalent. (But I am rather sure that gcc isn't that good.)
Furthermore, casinh etc are not commonly used functions. Putting huge
amounts of effort looking at special cases to speed it up a little
somehow feels wrong to me. In fact, if the programmer knows that he
will be wanting casinh, and evaluated very fast, then he should be
motivated enough to try out using z in the case when |z| is small, and
see if that really speeds things up.
Stephen
More information about the freebsd-numerics
mailing list