
"Gerhard Wesp" wrote
Sorry, I don't have the time to read the PQS documentation in-depth right now.
Still, I'd like to make one suggestion.
I think that handling of dimensional quantities and conversion factors are orthogonal concepts and should be separated.
They are in PQS. This is the distinction between abstract and concrete quantities and units in the documentation. However in source code it is more convenient to combine these elements in one type. This is the t1_quantity. t1_quantity can be passed as a template parameter carrying all the dimension and unit information with it. This is not possible with external constants or doubles etc.
I suggest that for maximum transparency the library should *exclusively* handle quantities expressed in SI units.
Unfortunately in everyday life non-si units crop up frequently.
I'm aware that this "mildly forces" developers to adopt SI units. I consider this a Good Thing.
PQS tries to favour SI quantities over non SI ones. By using SI quantities rather than non-SI ones, you will get faster and more accurate results for example.
Conversion factors between non-SI units and SI units should be constant dimensional quantities, e.g. (assuming constructors from double):
const length foot = .3048 ; // Meter const power european_horse_power = 735.4987 ; // Watt const mass pound = 0.4535924; // Kilogram
In PQS the constants are encoded as template parameters as part of the type. The unit defined in <boost/pqs/meta/unit.hpp> holds all the required information. Any mulltiplier is held as a rational. In the case of SI quantities the rational evaluates to 1 and this means that the rational can be optimised out of the calculation. Exponents are held as powers so multiplication of two si Quantities only involves multiplying runtime values. Any multiplication of their units is in fact addition of powers done at compile time. This makes for much faster and more accurate calculations. Consider the calculation 1 km * 1 millisecond. The external units approach 1 * km * 1 * millisecond, which expanding the constants would be 1 * 1000. * 1 * .001 In pqs the internal calculation at runtime is simply 1. * 1. The type of the result encodes the calculation 1000 * .001 as plus<3,-3>::value in the unit of the result. In pqs the user doesnt have to remember or look up the 'magic constants' that you describe below. This is an important point, because it means that quantities and conversions are potentially more consistent and predictable across applications.
This way, one could e.g. construct dimensional quantities like this: const power deux_chevaux = 2 * european_horse_power;
Non-SI quantities would have to stay "out of the system" in normal floating point variables:
length altitude; double altitude_ft = altitude / foot;
Ignoring dimensionality, this is the notation Mathematica chooses.
I have done some engineering simulations, written a flight simulation framework and used one that uses US units (D6; see www.bihrle.com).
A goal of pqs is to be useable in that sort of situation. To be really effective it will need a lot of supporting classes ( matrix, vector, quat) though.
The D6 source code is riddled with magic constants. I've collected some conversion constants in units.h of cpp-lib, see http://gwesp.tx0.org/software/.
One function of pqs is to provide these constants for conversion in a consistent way. It is of course possible to extract them from the headers without using the rest of the library too. regards Andy Little