Re: [boost] [review] pqs

----Original Message---- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andy Little Sent: 08 June 2006 17:46 To: boost@lists.boost.org Subject: Re: [boost] [review] pqs
Although liter is equivalent to 1 dm^3, technically its not an SI unit. Its not in the review version of PQS, but it is possible to add a liter unit to volume header and get output as
1 L
or whatever is preferred... I just did this in my local version of PQS.
The sequence of steps is
1) In <boost/pqs/meta/components/of_volume.hpp>
Add a typedef for the liter in the incoherent_unit struct (starts at line 47). [SNIP]
That is not good. Not good at all. As far as I am concerned, a third party library file is (almost) sacrosanct. I would not want to edit it except to fix the most extreme bug - what happens when I upgrade to the next version of PQS. Can I add liter support externally to PQS? (For example, so I can refer to "litre").
typedef meta::unit< boost::pqs::meta::rational<-3>, meta::rational<1>::type, boost::mpl::int_<1> > liter;
2)
In <boost/pqs/t1_quantity/types/volume.hpp>
Add the typedef for liter to the other member typedefs:
typedef t1_quantity< type, typename incoherent_unit::liter, Value_type > liter;
3) In <boost/pqs/t1_quantity/types/out/volume.hpp> add the stream output overload for the liter unit:
inline std::ostream& operator <<( std::ostream & os, t1_quantity_units_out< meta::components::of_volume::type, meta::components::of_volume::incoherent_unit::liter > ) { os << "L"; return os; }
Check it works:
#include <boost/pqs/t1_quantity/types/out/volume.hpp> using boost::pqs::volume;
int main() { volume::liter v(1); std::cout << v <<'\n'; volume::m3 v1 = v; std::cout << v1 <<'\n'; }
Outputs:
1 L 0.001 m3
Because liter isnt an SI unit you would need to add cL and mL in the same way (I guess that would be the next question!)
regards Andy Little
-- Martin Bonner Martin.Bonner@Pitechnology.com Pi Technology, Milton Hall, Ely Road, Milton, Cambridge, CB4 6WZ, ENGLAND Tel: +44 (0)1223 203894

"Martin Bonner" wrote [adding PQS quantity units info cut]
That is not good. Not good at all.
FWIW David Walthall suggested another scheme by which the struct used as a container for the units was derived from another struct in another header in a user directory intended for the user to be able to add their own units. Would that be an improvement? regards Andy Little

In response to Andy's instructions about how to add a liter:
1) In <boost/pqs/meta/components/of_volume.hpp>
Add a typedef for the liter in the incoherent_unit struct (starts at line 47). typedef meta::unit< boost::pqs::meta::rational<-3>, meta::rational<1>::type, boost::mpl::int_<1> > liter;
Martin Bonner wisely noted that one should not edit the library itself:
As far as I am concerned, a third party library file is (almost) sacrosanct. I would not want to edit it except to fix the most extreme bug - what happens when I upgrade to the next version of PQS.
So with above citation to bring the context, the problem is that it's not easy to add new unit types. After short private correspondence with Andy I think there is a solution for that. Instead of modifying the source code of the library, just add there following macro (macro name can be different of course): #define BOOST_UNITS_DIVIDED(numerator,denominator,new_type) \ typedef /*typename */ pqs::meta::binary_operation< \ numerator, \ pqs::meta::divides, \ denominator \ >::type new_type \ (this macro works in boost 1.33 - without boost::typeof. A similar macro can be written to utilize boost::typof. Of course a second macro BOOST_UNITS_MULTIPLIED would be needed as well) This macro allows to define custom units with small trouble - just write the unit components. Taking example from my review - I had problems with a unit N/m (spring stiffness). With above macro I just write one line: BOOST_UNITS_DIVIDED(pqs::force::N,pqs::length::m,N_div_m); and now I have a new type named N_div_m and I can use it as desired. With this mechanism maybe the amount of predefined units can be reduced - maybe even only to one unit per dimension and no mixed units at all? (not sure about that though). The point is that the user can define only those units that he is going to use in his program. IMHO adding this macro will increase pqs' library capabilities a lot. -- Janek Kozicki |

Janek Kozicki wrote:
Instead of modifying the source code of the library, just add there following macro (macro name can be different of course):
#define BOOST_UNITS_DIVIDED(numerator,denominator,new_type) \ typedef /*typename */ pqs::meta::binary_operation< \ numerator, \ pqs::meta::divides, \ denominator \
::type new_type \
(this macro works in boost 1.33 - without boost::typeof. A similar macro can be written to utilize boost::typof. Of course a second macro BOOST_UNITS_MULTIPLIED would be needed as well)
This macro allows to define custom units with small trouble - just write the unit components. Taking example from my review - I had problems with a unit N/m (spring stiffness). With above macro I just write one line:
BOOST_UNITS_DIVIDED(pqs::force::N,pqs::length::m,N_div_m);
and now I have a new type named N_div_m and I can use it as desired.
IMHO adding this macro will increase pqs' library capabilities a lot.
This is interesting and useful. However, it still doesn't solve the problem of how to define units in a completely different system than SI. Folks have mention particle physics as one domain where this is needed. I've talked talked about units where the prefixes are not powers of 10 (specifically, Mibibytes, etc.). So this is a good start but it needs to go further. I'm ok with more work to define such non-SI units but it shouldn't be any more difficult than someone defining an SI without the handy macro. In other words, I think things can be designed with flexibility in mind and the SI units presented as an implementation on top of that framework. The SI units becomes a "library" on top of the "framework." No need to pqs to implement all unit systems. Just one demonstration with a widely-used system (SI) is enough. Others can contribute other units libraries as desired. -Dave

"Janek Kozicki" wrote
So with above citation to bring the context, the problem is that it's not easy to add new unit types. After short private correspondence with Andy I think there is a solution for that.
Instead of modifying the source code of the library, just add there following macro (macro name can be different of course):
#define BOOST_UNITS_DIVIDED(numerator,denominator,new_type) \ typedef /*typename */ pqs::meta::binary_operation< \ numerator, \ pqs::meta::divides, \ denominator \
::type new_type \
(this macro works in boost 1.33 - without boost::typeof. A similar macro can be written to utilize boost::typof. Of course a second macro BOOST_UNITS_MULTIPLIED would be needed as well)
This macro allows to define custom units with small trouble - just write the unit components. Taking example from my review - I had problems with a unit N/m (spring stiffness). With above macro I just write one line:
BOOST_UNITS_DIVIDED(pqs::force::N,pqs::length::m,N_div_m);
and now I have a new type named N_div_m and I can use it as desired.
Hopefully boost 1.34 will be released soon. Then Boost.Typeof will provide a generic solution to this problem rather than requiring a macro for each expression, Boost.Typeof can handle expressions of arbitrary complexity directly and IMO will be found to be extremely useful both inside and outside PQS library. IMO the fastest way to get full language support for decltype and auto(see below links): is to show how useful Boost.Typeof is and use it, use it, use it in preference to other type deduction schemes http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1478.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1527.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1705.pdf
With this mechanism maybe the amount of predefined units can be reduced - maybe even only to one unit per dimension and no mixed units at all?
I think there is a case for providing what I would call different 'views'. I have concentrated on one 'view' in which the units are explicitly spelt out. that is the one dealing with named-quantities, typedefs for particular units ( pqs::length::m) , etc, etc. This is helpful when unit conversions are needed. However, (though I havent looked in real detail at yade yet) http://yade.berlios.de/ from the current brief look I have had so far it occurs that for this type of use a different view, created by just typedefing quantities for their names (length, time, force etc) in implied base units, would be more suitable.( In yade I think the unit conversion capability is irrelevant ?). This type of use would also facilitate being able to switch PQS library in for dimensional analysis checking and then switch the library back to floating point types for max performance of the release version. In this case use of other than base units wouldnt be suitable, though even here unit conversions could be achieved ( maybe via the alternate syntax favoured by Walter Browns SI Units and Jesper Schmidt), if necessary. regards Andy Little

Hello, Actually when I was writing a review I have written a leghty paragraph about unit scaling during serialization. But later I decided that review is not a good place to put it, so I'm pasting it now below: One of my first thoughts was about making it easier for the end user to perform serialization, more precisely, consider the first screenshot in following URL: http://yade.berlios.de/index.php?m=700:70 You can see here "File Generator" window, in the bottom part of this window all attributes registered for serialization of class BoxStack (which derives from FileGenerator) are displayed. Yade has it's own serialization library which currently supports binary format, xml and QT dialog boxes, so basically here visible is the result of serialization with QT backend. The idea is about user interface for this dialog box. I would like to add a drop-down menu next to the each phisical quantity in this window. So for example (as seen on the screenshot) single line: +-----------------------+ dampingForce : | | +-----------------------+ would now look like: +----------------+ +----+ dampingForce : | | | kN | +----------------+ +-\/-+ Where the drop-down menu would show for example "N","kN","MN", etc... Either all of them (including even uN), or more preferably only those that have been typedefind (or included) by the user of the library. Then yade user willl be able to chose the unit he wants from the menu, then enter the value. To acheive this in the library I would need following interface, first a function which returns a list of all allowed names for a given named_quantity, for example: const std::vector<std::string>& get_unit_names(); With this list I can initialize the drop-down menu. Next I need the ability to initialize a named quantity by a combo of numerical_value and std::string. Where std::string is of course the unit name chosen by the user (eg. "kN"), like this: // in some place of code (in BoxStack.hpp, actually) pqs::force::N dampingForce; // then inside qt-serialization backend: // this value is typed by the user into the dialog box double forceValue; // unit magnitude is selected by the user from the drop-down menu std::string unitName="kN"; // call constructor to assign the value intended by the user dampingForce=pqs::force::N(forceValue,unitName); I'm sure that above interface would be similarly useful to give greater functionality to plain old cin >> . Actually cin >> seems to have exactly those problems which above could solve: #include <boost/pqs/t1_quantity/types/out/length.hpp> #include <boost/pqs/t1_quantity/io/input.hpp> namespace pqs = boost::pqs; int main() { pqs::length::mm length; // type "123 mm" - and it works, type "123 m" - and it doesn't work std::cin >> length; std::cout << length << '\n'; } I presume that only t2_quantity gives what I need above. But if conversion from t2_quantity to t1_quantity is possible, then maybe all that t1_quantity -> t2_quantity -> t1_quantity conversions could be hidden from the user behind the interface? So that only those two interface functions I mentioned above will be used. PS: please note that this comment is *old* so I'm still using here old names (t1, t2,...) and other stufff that likely is already decided that it will be modified to better suit the needs/suggestions/comments of all people. But the need for described above interface still remains. -- Janek Kozicki |

"Janek Kozicki" <janek_listy@wp.pl> wrote in message news:20060618012322.3c3a0a29@absurd...
Hello,
Actually when I was writing a review I have written a leghty paragraph about unit scaling during serialization. But later I decided that review is not a good place to put it, so I'm pasting it now below:
One of my first thoughts was about making it easier for the end user to perform serialization, more precisely, consider the first screenshot in following URL:
*Even* with t1_quantity (fixed units) you would get some 'free' units output ;-) [cut user settable units]
I presume that only t2_quantity gives what I need above. But if conversion from t2_quantity to t1_quantity is possible, then maybe all that t1_quantity -> t2_quantity -> t1_quantity conversions could be hidden from the user behind the interface? So that only those two interface functions I mentioned above will be used.
Yes. t2_quantity should be useful for that. Typically you can make a units map<unit_string, quantity_w_unit>. t1_quantity is useful to describe the quantity_w_unit, t2_quantity to hold runtime unit and convert to t1_quantity I had an example, but in a previous version of PQS. Not tried to make a GUI widget of it yet though ;-)
PS: please note that this comment is *old* so I'm still using here old names (t1, t2,...) and other stufff that likely is already decided that it will be modified to better suit the needs/suggestions/comments of all people. But the need for described above interface still remains.
Yep ... todo! regards Andy Little

Andy Little said: (by the date of Mon, 19 Jun 2006 21:52:11 +0100)
PS: please note that this comment is *old* so I'm still using here old names (t1, t2,...) and other stufff that likely is already decided that it will be modified to better suit the needs/suggestions/comments of all people. But the need for described above interface still remains.
Yep ... todo!
thanks! I'm looking forward to next submission. And also I offer my help if you need anything to be tested or discussed, just ask :) -- Janek Kozicki |

"Janek Kozicki"
Andy Little said: (by the date of Mon, 19 Jun 2006 21:52:11 +0100)
PS: please note that this comment is *old* so I'm still using here old names (t1, t2,...) and other stufff that likely is already decided that it will be modified to better suit the needs/suggestions/comments of all people. But the need for described above interface still remains.
Yep ... todo!
thanks! I'm looking forward to next submission. And also I offer my help if you need anything to be tested or discussed, just ask :)
OK, thanks Janek :) regards Andy Little

Andy Little said: (by the date of Wed, 14 Jun 2006 21:27:34 +0100)
With this mechanism maybe the amount of predefined units can be reduced - maybe even only to one unit per dimension and no mixed units at all?
I think there is a case for providing what I would call different 'views'. I have concentrated on one 'view' in which the units are explicitly spelt out. that is the one dealing with named-quantities, typedefs for particular units ( pqs::length::m) , etc, etc. This is helpful when unit conversions are needed.
Yes, those particular typedefs (when unit conversions are needed) could be included from separate file.
However, (though I havent looked in real detail at yade yet)
from the current brief look I have had so far it occurs that for this type of use a different view, created by just typedefing quantities for their names (length, time, force etc) in implied base units, would be more suitable. ( In yade I think the unit conversion capability is irrelevant ?).
Actually I was thinking about using conversions, but only for serialization purposes. So yade internally uses the base SI units, but during input/output the user can pick the desired units from dropdown menu. But (very important) this process is handled ONLY by serialization module and converts the input to the base SI unit. So that whole rest of yade doesn't have to care about that and safely assume that all the calculations are in base SI unit - as it is currently now. I will reitarate - unit scaling (MN vs. kN vs. N) belongs to serialization.
This type of use would also facilitate being able to switch PQS library in for dimensional analysis checking and then switch the library back to floating point types for max performance of the release version.
yes, good point.
In this case use of other than base units wouldnt be suitable,
Yes, but remember that it's the library user who choses the base units in his calculations. I can pick base SI units, but physicists will pick electronovolt as a base unit, and speed of light = 1.
though even here unit conversions could be achieved ( maybe via the alternate syntax favoured by Walter Browns SI Units and Jesper Schmidt), if necessary.
Yes, I prefer this syntax (as a reminder): Jesper Schmidt wrote:
In generel I have a hard time understanding the motivation for introducing unit-types instead of just quantity types. Personally I prefer length x = 10 * meter(); to length::m_div_s x(10) because the former is closer to the syntax from the real SI system.
And with this macro from parent post, and other macros suppyling this one, and perhaps with boost typeof, this Jesper's machanism can be quite easy to acheive. -- Janek Kozicki |
participants (4)
-
Andy Little
-
David A. Greene
-
Janek Kozicki
-
Martin Bonner