X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f X-Recipient: geda-user AT delorie DOT com X-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=aFb2dZKtnUraNRFNnqLsqAMjEk8i9FBDCXorRRVTjh4=; b=M5ruIAJf5h0gLnVvPgEsmKvWTCoasyfYRz1a7ZFo8rABbNzk2iM1PXcy7RGk5IailS UcJET9/O6iEC6ImaVi3/am5DYJ8M/P7HuRrMAyy86l92l9IIQ4pT5tEydpon0TB+rS22 KKHjwV8QgxyUoYEXAc7j5a0DwPjqZHdvLqyY1QRSmCmUHnJkn8+oIyI3JILkEA29wVfB DqOgnE3/r61lYThGpeQKNJEVx/WgeoahI+th87+GDd7qdWYaK0eht6kOlbZhnDruB6Ib ycfn2YFd77eUncz3/D5QHee34lwbXhxQ2fmMfBaeQ1q40gfiGhJf0PVNVUJ0GPmpHbGM neHQ== MIME-Version: 1.0 X-Received: by 10.194.173.233 with SMTP id bn9mr110205111wjc.1.1452126555620; Wed, 06 Jan 2016 16:29:15 -0800 (PST) In-Reply-To: References: Date: Wed, 6 Jan 2016 15:29:15 -0900 Message-ID: Subject: Re: [geda-user] Re: some more geometry module tweaks (sorry, wall of text) From: "Britton Kerin (britton DOT kerin AT gmail DOT com) [via geda-user AT delorie DOT com]" To: geda-user AT delorie DOT com Content-Type: multipart/alternative; boundary=089e0122f088844e700528b38f36 Reply-To: geda-user AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: geda-user AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk --089e0122f088844e700528b38f36 Content-Type: text/plain; charset=UTF-8 > > >> Hmm. I had intended the geometry.h as a sort of portable source library, >> without any encapsulated pcb-specific decisions. As it happens I already >> have pcb_geometry.h as well which does some adaptation. Perhaps the >> latter >> just needs to grow a bit, at which point our ideas of how to handle this >> are >> probably about the same. >> > > Sounds good. I'll start "drawing" because I am not sure I can follow the > details. Upper libs depend on lower libs. > > A pcb > B pcb-specific-geo (often with complex pcb types) > C generic-geo > > So you say C does everything in floating point, and B is responsible for > proper rounding/conversions? Or did I get the whole stack wrong? > You've pretty much got it. B would maybe also be responsible for doing something intelligent with degenerate inputs (where pcb allows them) and maybe some obnoxious cases for which there is no obvious generally correct floating point approach (e.g. arcs of identical or nearly identical circles). I admit that by the time you do all this it gets tempting to roll your own fixed-point math.h, but I suspect there are a lot of subtle traps there as well. Britton > > > > > >> Here's one attempt at a general approach to this problem: >> >> >> http://www.gnu.org/software/gsl/manual/html_node/Approximate-Comparison-of- >> >> Floating-Point-Numbers.html#Approximate-Comparison-of-Floating-Point-Number >> s >> > > Nice! > > > >> I'm not sure about this. A wider float type can actually represent >> everything in a narrower int type. Consider: >> >> #include >> #include >> #include >> #include >> >> int >> main (void) >> { >> printf ( >> "INT32_MAX: %i\n", INT32_MAX); >> printf ( >> "pow (FLT_RADIX, DBL_MANT_DIG) - 1: %f\n", >> pow (FLT_RADIX, DBL_MANT_DIG) - 1 ); >> printf ( >> "pow (FLT_RADIX, DBL_MANT_DIG): %f\n", >> pow (FLT_RADIX, DBL_MANT_DIG) ); >> printf ( >> "pow (FLT_RADIX, DBL_MANT_DIG) + 1: %f\n", >> pow (FLT_RADIX, DBL_MANT_DIG) + 1 ); >> >> return 0; >> } >> >> which gives: >> >> $ gcc --std=c11 -Wall -Wextra -Werror text.c >> $ ./a.out >> INT32_MAX: 2147483647 >> pow (FLT_RADIX, DBL_MANT_DIG) - 1: 9007199254740991.000000 >> pow (FLT_RADIX, DBL_MANT_DIG): 9007199254740992.000000 >> pow (FLT_RADIX, DBL_MANT_DIG) + 1: 9007199254740992.000000 >> $ >> >> The largest double to which you can count "by ones" is much greater than >> INT32_MAX. >> > > > > Yes, the relationship must be such that e.g. pow (FLT_RADIX, DBL_MANT_DIG) >> > >> INT32_MAX (or whatever largest coord you want to handle), or else you have >> to worry about the exact consequences for every case (impractical). >> > > > Yup, this is generally true, and double has more bits than int32. However, > I think you should also cosinder the x^2 cases: what happens to an > sqrt(x^2), if x^2 was in the range of 2^31? > Yeah DJ hinted at this as well. My knee-jerk reaction is to use an even winder type for the internal floating point representation. Short of arbitrary precision there's no way to support arbitrary intermediate results, but if you can count bye ones all the way to a squared value that would seem to cover all the simple geometrical calculations we're interested in. Things like hypot() help, but I admit I don't fully understand exactly how much. They certainly keep the numbers smaller and thereby prevent overflow, but I don't fully understand the consequences for intermediate results outside the range where the float can represent all integers. Unfortunately people think of long doubles as flaky and I have this impression also. Still, the real question is their relative flakiness compared to everything else. Probably none of this matters and int coordinates with double calculations inside are fine, but it would be nice to feel certain. Britton --089e0122f088844e700528b38f36 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

=
<snip>
Hmm.=C2=A0 I had intended the geometry.h as a sort of portable source libra= ry,
without any encapsulated pcb-specific decisions.=C2=A0 As it happens I alre= ady
have pcb_geometry.h as well which does some adaptation.=C2=A0 Perhaps the l= atter
just needs to grow a bit, at which point our ideas of how to handle this ar= e
probably about the same.

Sounds good. I'll start "drawing" because I am not sure I can= follow the details. Upper libs depend on lower libs.

A pcb
B pcb-specific-geo (often with complex pcb types)
C generic-geo

So you say C does everything in floating point, and B is responsible for pr= oper rounding/conversions? Or did I get the whole stack wrong?

You've pretty much got it.=C2=A0 B would maybe = also be responsible for doing something intelligent with degenerate inputs = (where pcb allows them) and maybe some obnoxious cases for which there is n= o obvious generally correct floating point approach (e.g. arcs of identical= or nearly identical circles).

I admit that by the= time you do all this it gets tempting to roll your own fixed-point math.h,= but I suspect there are a lot of subtle traps there as well.
=C2= =A0
Britton





<snip>
Here's one attempt at a general approach to this problem:

http://www.gnu.org/softwa= re/gsl/manual/html_node/Approximate-Comparison-of-
Floating-Point-Numbers.html#Approximate-Comparison-of-Floating-Point-Number=
s

Nice!

<snip>
I'm not sure about this.=C2=A0 A wider float type can actually represen= t
everything in a narrower int type.=C2=A0 Consider:

=C2=A0 =C2=A0 =C2=A0#include <float.h>
=C2=A0 =C2=A0 =C2=A0#include <stdint.h>
=C2=A0 =C2=A0 =C2=A0#include <math.h>
=C2=A0 =C2=A0 =C2=A0#include <stdio.h>
=C2=A0=C2=A0
=C2=A0 =C2=A0 =C2=A0int
=C2=A0 =C2=A0 =C2=A0main (void)
=C2=A0 =C2=A0 =C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0printf (
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "INT32_MAX: =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0%i\n&q= uot;, INT32_MAX);
=C2=A0 =C2=A0 =C2=A0 =C2=A0printf (
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"pow (FLT_RADIX, DBL_MANT_DIG= ) - 1: =C2=A0%f\n",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pow (FLT_RADIX, DBL_MANT_DIG) - 1 = );
=C2=A0 =C2=A0 =C2=A0 =C2=A0printf (
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"pow (FLT_RADIX, DBL_MANT_DIG= ): =C2=A0 =C2=A0 =C2=A0%f\n",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pow (FLT_RADIX, DBL_MANT_DIG) ); =C2=A0 =C2=A0 =C2=A0 =C2=A0printf (
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"pow (FLT_RADIX, DBL_MANT_DIG= ) + 1: =C2=A0%f\n",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pow (FLT_RADIX, DBL_MANT_DIG) + 1 = );

=C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
=C2=A0 =C2=A0 =C2=A0}

which gives:

=C2=A0 =C2=A0 =C2=A0 $ gcc --std=3Dc11 -Wall -Wextra -Werror text.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 $ ./a.out=C2=A0
=C2=A0 =C2=A0 =C2=A0 INT32_MAX: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A02147483647
=C2=A0 =C2=A0 =C2=A0pow (FLT_RADIX, DBL_MANT_DIG) - 1: =C2=A090071992547409= 91.000000
=C2=A0 =C2=A0 =C2=A0pow (FLT_RADIX, DBL_MANT_DIG): =C2=A0 =C2=A0 =C2=A09007= 199254740992.000000
=C2=A0 =C2=A0 =C2=A0pow (FLT_RADIX, DBL_MANT_DIG) + 1: =C2=A090071992547409= 92.000000
=C2=A0 =C2=A0 =C2=A0$=C2=A0

The largest double to which you can count "by ones" is much great= er than
INT32_MAX.

<snip>

Yes, the relationship must be such that e.g.=C2=A0pow (FLT_RADIX, DBL_MANT_= DIG) >
INT32_MAX (or whatever largest coord you want to handle), or else you have<= br> to worry about the exact consequences for every case (impractical).


Yup, this is generally true, and double has more bits than int32. However, = I think you should also cosinder the x^2 cases: what happens to an sqrt(x^2= ), if x^2 was in the range of 2^31?

Yeah DJ hinted at this as well.=C2=A0 My knee-jerk reaction is to u= se an even winder type for the internal floating point representation.=C2= =A0 Short of arbitrary precision there's no way to support arbitrary in= termediate results, but if you can count bye ones all the way to a squared = value that would seem to cover all the simple geometrical calculations we&#= 39;re interested in.=C2=A0 Things like hypot() help, but I admit I don'= t fully understand exactly how much.=C2=A0 They certainly keep the numbers = smaller and thereby prevent overflow, but I don't fully understand the = consequences for intermediate results outside the range where the float can= represent all integers.

Unf= ortunately people think of long doubles as flaky and I have this impression= also.=C2=A0 Still, the real question is their relative flakiness compared = to everything else.

Probably= none of this matters and int coordinates with double calculations inside a= re fine, but it would be nice to feel certain.
=C2=A0
Britton

--089e0122f088844e700528b38f36--