[cairo] Shouldn't Cairo use/offer degrees rather than radians?

David Kastrup dak at gnu.org
Tue Jul 11 18:11:26 UTC 2017


Bill Spitzak <spitzak at gmail.com> writes:

> On Mon, Jul 10, 2017 at 10:10 PM, David Kastrup <dak at gnu.org> wrote:
>> Gregor M├╝ckl <GregorMueckl at gmx.de> writes:
>>
>>> Don't pin this only on the compiler, at least on x86. The old x87
>>> compatible FPU instructions (obsolete in 64 bit mode) use internal
>>> registers with significant longer mantissa than a double. The length
>>> of the mantissa was not even fixed between implementations. However,
>>> storing values from the FPU to memory results in truncation in this
>>> case. This was "fixed" in SSE and newer intruction sets that are now
>>> fixed at 32 bits for floats and 64 bits for doubles for internal
>>> registers.
>>>
>>> I believe that this thread is starting to demonstrate that hunting for
>>> numeric precision beyond a certain point using floating point
>>> arithmetic is a fool's errand.
>>
>> The proposed code for setting angles in degrees is numerically precise
>> at right angles for any floating point representation.
>>
>> Stuff like M_PI/2 or even M_PI will always result in hunts for numeric
>> precision since pi does not have an exact floating point representation.
>>
>> This thread was about a proposed user interface that makes hunting for
>> numeric precision a non-issue for the most prominent cases while
>> representing angles in a common human-accessible format that other
>> graphic systems and formats use as well.
>>
>> So the conclusion "let's not bother offering something better because we
>> cannot conclusively figure out how bad the current situation is on
>> different systems respectively" is not really what I was pitching for.
>
> The problem is that it is not better, and providing the api will
> mislead people into thinking it is better.

This API can turn exactly by multiples of 90 degrees.  The existing API
cannot.

> You wanted two rotates by 45 degrees to be perfect.

Uh, no?  Two rotates by 45 degrees illustrate a _compromise_.  The
degree of rotation will generally be a perfect 90 degrees because of all
rotation matrix elements having the same magnitude, the total magnitude
(determinant of the scaling matrix I think) will lightly be slightly
more wrong than the magnitude of the radian API (which likely also fails
to be 1 due to sin/cos of M_PI/4 in floating point also being
approximations).

> However that is not how Cairo is implemented and changing it would
> require considerable effort for no real win. A rotate of 45 degrees is
> turned into a matrix containing sqrt(2)/2 which is not stored
> accurately.

Did you even read the patch and its rationale?  Or are you making up
that straw man on the fly?  Multiples of 90 degrees are perfect.  There
are currently several fast paths in Cairo's code paths which actually
_check_ for that kind of perfection.

> The exact same value is stored whether the rotation is sent as degrees
> or radians.

DID YOU LOOK AT THE PATCH?????  I cannot believe you did when you state
this.

> Any implementation that blindly does sin(angle*(M_PI/180)) will
> produce the exact same error for right angles whether they are given
> in degrees or radians.

The patch I sent did not do this.

> So simply making the api be degrees with the easiest implementation
> will not fix anything.

DID YOU LOOK AT THE PATCH?????

To make this easier for you, I append it _again_ as an attachment to
this mail.

> I would like to make a more limited request of Cairo:
>
> 1. Change cairo_matrix_init_rotate to detect multiples of M_PI_2 and
> produce integers.

This does not work reliably because pi and consequently pi/2 do not have
exact floating point representations.  As a result, M_PI+0.5*M_PI may or
may not be equal to 1.5*M_PI.  This has to interpret values as something
that they aren't and consequently introduces errors.  You'd need to work
with tolerances, and every window of tolerance is equivalent to a window
of erroneous interpretation.  You'd need different windows for every
different floating point format.

In contrast, 0, 45, 90, ... have exact floating point representations in
any commonly used floating point format.

> From what I can see subtracting M_PI_2*n where n is
> rint(angle/M_PI_2), and then doing sin/cos works pretty good. This
> will prevent surprises in the resulting matrix. I tested some stuff in
> gnuplot and any discontinuity in the plots is below 2e-16.
>
> 2. Add an api to rotate so the x axis passes through an x,y point (and
> possibly scales by hypot(x,y)). This would provide an "accurate"
> rotate for a whole lot of cases that actually come up in real
> graphics.

For multiples of 90 degrees, you can "trivially" just specify the
transform matrix, yet nobody does.  This is not how people think, and we
are talking about an API for people.

David Kastrup

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Implement-cairo_matrix_init_rotate_deg-and-cairo_mat.patch
Type: text/x-diff
Size: 5889 bytes
Desc: not available
URL: <https://lists.cairographics.org/archives/cairo/attachments/20170711/16acf484/attachment-0001.patch>


More information about the cairo mailing list