Mail Archives: geda-user/2016/01/05/04:08:20
On Tue, Jan 05, 2016 at 04:27:33AM +0100, gedau AT igor2 DOT repo DOT hu wrote:
>
>
> On Mon, 4 Jan 2016, Peter Clifton (petercjclifton AT googlemail DOT com) [via geda-user AT delorie DOT com] wrote:
>
> >
> >
> >On 4 Jan 2016 19:48, "DJ Delorie" <dj AT delorie DOT com> wrote:
> >>
> >>
> >>> With regards rewriting geometry functions, I'd be interested in a why -
> >if
> >>> they already worked. The old code looking ugly would be a fine reason,
> >just
> >>> be extra sure the replacements will be well behaved ;)
> >>
> >>They were being duplicated all over the place. We discussed this a
> >>while back and agreed that collecting all the 2D/3D generic math
> >>functions in one spot made sense.
> >
> >I'm drawing a distinction here between "collecting" and "rewriting". The
> >later needs at least some justification.
> >
>
> I am not sure about the state of the git head mainstream version,
> I'm talking about pcb-rnd (forked from a 2013 verison of pcb).
>
> While working on the cycle drag and semi-related negative box
> selection, I needed a few calls that decided whether objects touch
> an axis aligned box.
>
> I though there was some easy way to do this with existing infra, but
> couldn't find anything trivial. I figured there were two problems:
>
> 1. There was no much generic geometric "does this line intersect
> that circle" like code; instead, search.c has some IsPointOnLine()
> and co., which take complex PCB object type as one end of the
> comparison. This is totally fine for DRC, but if you want to
> implement something else and you really need to check aritrary
> theoretical objects, they can't be reused.
>
> 2. Other parts of the code seem to struggle with this. The solution
> is, as DJ said, is that everyone coded something locally. A random
> example is the "rubber_callback()" that checks if a line touches a
> selection box.
>
> Since the coordinate type is an integer (I consider it sort of a
> fixed point number, as it is in nanometer), and values are large,
> calculations may overflow. E.g. assume signed 32 bit coords, you get
> about 2.1 meters as max board size. Now look at rubber_callback():
> at some point it does an x*=x. This means x has to be wider than
> int32_t else the actual limit comes down to sqrt(2.1).
Confused, sqrt(2^31) is about 46000, so that's 46µm.
> In that piece
> of code the "intermediate calculation type" is double. This could
> work well with 32 bit coords as double provides 53 bit base. However
> if the user configures pcb to use 64 bit coords, this is not true
> anymore (although the board needs to be ireally big to reach 53
> bits). Theoretically we'd either need some clipping on the int coord
> side or long doubles for intermediate calculations. When converting
> between ints and floats, there may be some system specific behaviour
> around rounding - some code doesn't seem to care about this.
Please, do no use long doubles for anything. While doubles are more or
less standardized on IEEE-754 (or 854?) representation (there are
variations wrt the bit-level representation of NaN and infinities),
there are at least 4 different flavours of long doubles I know of:
1) 80 bit as used with the essentially obsolete x87 FPU and its weird
stack. On modern Intel/AMD processors it is often quite slow, as this
is considered a legacy feature which drove compiler writers crazy.
The 68000 coprocessors also used this format.
2) 128 bit genuine quad precision, only implemented in hardware on IBM
mainframes (http://arith22.gforge.inria.fr/slides/s1-schwarz.pdf,
pages 24--25), otherwise emulated and much slower. (Unfortunately
I can't afford such a machine...). Recent patches to binutils and gcc
indicate that Power9 should also have hardware support. But this is
not commonplace.
3) 128 bit by using 2 64 bit doubles, called "IBM long double" as
implemented in some PPC libraries. Likely on its way to obsolescence.
4) same as plain double, zero advantage, only adds to confusion in the
source code.
The worst drawback is that the choice of the representation often
depends on compiler options. GCC has __float128, but it's likely
compiler specific.
Realistically, standard IEEE-754 doubles are good enough in practice and
available on all platforms I'd expect you to run PCB (you're not running
it on a VAX, are you?). There are still minor variations:
- 32 bit x86 will by default use a higher precision for the mantissa
during intermediate computations on the x87 stack.
- architectures with fma (fused multiply add) instructions (PPC, IA64,
others?). But fma is becoming the norm since it is available on recent
x86 processors, although I would not yet use it in packages for distributions.
This makes at least 3 cases which may give slightly different results
on critical dimension tests (maybr I've forgotten another variant).
>
> For all these, I think it's reasonable to create a centralized,
> generic (non-pcb-complex-type-oriented) geometry lib that could
> remove code duplication, could centralize the solution for
> clipping/rounding. Ideally the complex-pcb-type functions would deal
> with interpreting the types and then call the generic geometry
> functions too. It could not only help removing potential bugs but
> would ease adding new code that needs to deal with geometry.
>
Agreed.
Gabriel
- Raw text -