On 26 October 2015 at 22:51, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Dean Rasheed <dean.a.rasheed@gmail.com> writes:
>> Personally I'd rather have sind(30) be exactly 0.5, even if
>> sind(29.999...) or sind(30.000...1) ended up the wrong side of it.
>
> TBH, sir, if you think that you are too dangerous to be allowed anywhere
> near any numerical analysis code. Preserving mathematical properties like
> monotonicity is *far* more important than whether sin(30 degrees) comes
> out exact or not. You can do proofs about the behavior of algorithms
> using these functions if you can ensure monotonicity; but exactness of
> values is always going to depend on subtle details of the floating point
> format.
>
> I think using a range reduction to some fractional part of the circle is a
> reasonable way of trying to deal with these concerns, but I really really
> do not want to see it special-casing point values in a way that doesn't
> guarantee monotonicity.
>
OK, agreed. Preserving the monotonicity of sind over the range 0..90
is important. It's useful having this discussion before implementing a
lot of code that people might come to rely on.
> It may be that guaranteeing the sin(30) case is just not very feasible,
> and we should content ourselves with getting the 0/90/180/270/360 cases
> exactly, which we could do with a mod 90 initial reduction. Doing mod 30
> or mod 45 would require sewing together pieces of the curve that might not
> meet exactly, if we were unlucky. (I've not tried it though.)
>
I think it's still feasible to have sind(30) = 0.5 exactly and keep
monotonicity. If we can implement sind over the range 0..90, the rest
is easy, and in that range there are 3 known fixed points that we want
to preserve -- (0,0), (30,0.5) and (90,1). So all we need is a way to
compute each half of the range, interpolating between the fixed
points. That ought to be possible by pre-computing the value of
sin(pi/6) and using it to scale the result of sin(x) to guarantee that
the pieces join in the middle. (I've not tried it either, but it
sounds plausible.)
> What have you got in mind for tan() and the rest?
>
If we have sind() for the range 0..90, cosd() could be implemented as
sind(90 - x) after reducing x to the range 0..90, which would then
give it the right set of properties and it would be exact for 0, 60
and 90.
Then tand() and cotd() could be implemented as their ratios, which
would guarantee that tand(45) = cotd(45) = 1 exactly and that they are
monotonic nearby, without needing any special case code.
I haven't thought about the inverse functions yet, but they ought to
be possible in a similar way, albeit a bit fiddly.
Regards,
Dean