Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2006-08-26 14:43:55


"Deane Yang" <deane_yang_at_[hidden]> wrote in message
news:ecpndi$2mb$1_at_sea.gmane.org...
> Andy Little wrote:
>
>>> Can the dimension checking part of the library be used without the SI
>>> unit system? For most other unit systems I use, I mainly need
>>> dimension checking and not conversions between different units, such
>>> as km or m? Thus just a quantity with dimensions would be useful to
>>> catch programming errors.
>>
>> Yes. In the signature fixed_quantity<Unit, ValueType>, the Unit parameter
>> can
>> be so modelled that it only allows base units to be used, and in this case
>> there
>> is no conversion overhead BTW, a multiply is simply a multiply of the numeric
>> values for example). By default Quan wont work across Unit models (IOW the
>> class template names of units must match), which means that attempting to do
>> calculations between Units with different class template names will fail at
>> compile time. By this means you can guarantee that you can prevent any
>> conversions. (FWIW there is also the option to allow unit conversions but
>> make
>> them explicit, prompted by Deane Yang easrlier in this thread.)
>>
>
> I guess I wasn't particularly clear earlier in this thread, because
> fixed_quantity appears to be what I want. I'm sorry for not RTFM (I did
> try to read the documentation once, but my memory is not what it used to
> be), but I have two quick questions:
>
> 1) Does operator*(fixed_quantity<Unit1, ValueType1> x,
> fixed_quantity<Unit2, ValueType2> y) work and, if so, what is the result
> type, assuming that operator*(ValueType1 v, ValueType2 w) returns a
> ValueType3?

OK. The following relates to the CVS version currently on the two_param-branch,
but much applies to previous versions of Quan/PQS.

 Dealing with the ValueTypes first, the result type of ValueType1 * ValueType2
is encoded in the compile time expression:
binary_operation<ValueType1,times, ValueType2>::type.
The implementation provides a specialisation for inbuilt types, and this follows
the promotion/conversion rules on the respective calc in the C++ standard.
We have also been recently testing with boost::numeric::interval and (with the
appropriate specialisations) this seems to be working now and I believe that
other numeric UDT ValueTypes will now work OK.

The dimension of the result is found by adding the respective dimensions of the
operands. If the result is dimensioned, then in case of conforming SI
quantities the exponent of the conversion factor of the result is found by
adding the exponents in the conversion factors of the operands. For example a
pressure of 1 megapascale ( MPa) has a conversion-factor exponent of (10 to
power) 6. An area in square millimeters has a conversion-factor exponent of (10
to power) -6. The type resulting from multiplication of area::mm2 *
pressure::MPa is an anonymous type dimensionally equivalent to force, and has a
conversion factor exponent of 0, hence could be assigned directly to a force in
Newtons, without requiring a unit conversion.

Note also that (if you work through the maths) you will see that any dimensioned
multiplication (and division too FWIW) of 2 SI quantities is, at runtime, just a
direct multiplication of their numeric values. There is no unit conversion or
runtime scaling involved. The only time that a scaling may occur is when the
temporary result of the expression is assigned to an L_value in a different
unit, and this situation can now be detected, due to your suggestion to make
conversions explicit and it works rather nicely. IOW if you use SI quantities
then calculations in Quan can be as efficient as those calculated manually. Also
quantities with very large and small exponents can be used as efficiently as
base unit quantities.

The above may sound complicated, but if you think of how you would do the
calculation manually, then it should become clear what is going on.

If the result is dimensionless, then the result is a numeric, whose type is the
result type of multiplying the ValueTypes of the operands, as above( which must
obviously be multipliable else there will be a compile error). In this case the
calc first proceeds as for the dimensioned result case , but then the result
numeric value is divided by 10 to power of the exponent of the conversion
factor of the result (if the exponent is non zero), to give a pure number.

For non SI units it is as if the values were converted to the nearest SI units
before doing the multiplication and then the calculation proceeds as for the SI
unit case (In fact the latest version of Quan does a fair amount of
optimisation of all these calcs behind the scenes to try to remove any redundant
calculations and hence increase accuracy and calculation speed)

> 2) Can you raise a fixed_quantity to a rational power (I personally only
> need the power 1/2)?

Yes. here is an example. Note that because raising to a power affects the type
of the result, a special version of pow is required:

#include <quan/out/force.hpp>
int main()
{
   quan::force::N f(100);
   std::cout << quan::pow<1,2>(f) <<'\n';
}
output:
10 kg+1/2.m+1/2.s-1

regards
Andy Little


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk