andromeda-cad / andromeda-rfcs

AndromEDA development plans
0 stars 1 forks source link

Qt Reliance #10

Closed SchrodingersGat closed 6 years ago

SchrodingersGat commented 7 years ago

There has been some discussion on IRC regarding the level to which we rely upon the Qt libraries, with some in favour of having the back-end libs completely free of Qt code.

I would argue that as we are making a heavy dependency on Qt (for graphics and front-end) then why not make use of the high-level libraries that are available?

Disclaimer: I use Qt heavily and don't know much about STL or boost. I am happy to be dissuaded of this notion. My background is mainly embedded C and so I eschew many C++ idioms (mostly as I have not had need for them).

Some (very simple) examples that I can think of:

Discuss :)

SchrodingersGat commented 7 years ago

Some of the high-level Qt libs that I see us using no-matter what we do on the back-end (not an exhaustive list, I've just been reading up on them)

There are probably more examples too.

iromero91 commented 7 years ago

One problem with using QPoint is that is based on int, we want to use int64_t for the model, so conversions would be inevitable. It would be best if Qt types would be constrained to the view, and use a unified set of own types for the model and controllers.

SchrodingersGat commented 7 years ago

That's a fair point. Thinking about it some more, most of the graphics we'd be using (e.g. symbols, footprints, wires) would be rarely changed / edited, so most of the time we could convert a model to a Qt graphical representation and keep that in memory, and just continuously repaint with that (which can be translated, rotated, scaled) until the model itself changes.

iromero91 commented 7 years ago

Yeah we can use QPointF (double based), which should be a straight conversion from the fixed point as the reduced dynamic range makes it compatible.

Another option would be to just use floats in the model and encapsulate all arithmetics to be careful dealing with the odd cases floats might present, specially encapsulate comparison to use a proper epsilon value and discourage stuff that causes large roundoff errors like sum and accumulate (repeated addition instead of multiplying), and keeping proper hygiene regarding rounding once a calculation is made.

A double does not suffer underflow when adding a picometer to a kilometer

>>> 1000+1e-12
1000.000000000001

Nor does it have error to the last significant digit when multiplying 1 picometer by a very large number

>>> 1e-12*987654321098.0
0.987654321098

A more fair example. multiplying 1 meter+7pm times 1000, exact result should be 1000.000000007

>>> (1+7e-12)*1000.0
1000.0000000069999

Aha! it's not exact, but wait, didn't we say our epsilon is 1e-12?

>>> (1+7e-12)*1000.0-1000.000000007
-1.1368683772161603e-13

That is smaller than 1e-12, so those numbers compare equal! It is all in limiting the range of numbers to avoid underflow eating away precision, and using a realistic epsilon that will still leave us some guard bits when working within that range.

I have my doubts about using fixed point as a replacement for doing proper numerical analysis on the math operations, floats may try to be smart when you are stupid and don't consider issues like overflow, underflow and subnormal numbers, and instead of failing hard like fixed point would you would get subtle math errors that can be hard to track. That is more of an argument for properly testing the geometry routines, and give real test failures when they fail to deal with those extreme cases rather than relying on a system that will naturally blow up if you put it together wrong.