
I have spent a couple of hours looking at the units library. This is not a full review as I have not been able to compile my simple example in the time that I have available. I was motivated to write this review having yesterday needed to do some rather basic, but unfamiliar, physical calculations. At that time I used a simple awk script to do the arithmetic. If dimensional analysis had been available, it would have been a useful confidence builder that the code was doing the right thing. The problem was this: I have measured the temperatures on the surfaces of an electrical device - a power supply - and I want to calculate the power dissipated. The maths is simple: power = temperature difference to atmosphere * area * heat transfer coefficient. I tried to write this using the units library. Power, temperature and area were straightforward: typedef quantity<power> power_t; typedef quantity<area> area_t; typedef quantity<temperature> temp_diff_t; The units of the heat transfer coefficient are W C^-1 m^-2. As far as I was able to see, I was not able to write anything like typedef quantity<power/temperature/area> heat_transfer_coefficient_t; Rather, it was necessary for me to reduce W C^-1 m^-2 to basic dimensions manually. This is not easy for me. I have to remember phyics that I knew in 1988 but have not used much since. My guess was: power = energy / time energy = force * distance force = mass * acceleration acceleration = length / time^2 so I concluded that the dimensions of power are mass length time^-3 and hence of heat transfer coefficient are mass time^-3 temperature^-1 length^-1, and wrote this: typedef composite_dimension<mass_tag,1,time_tag,-3,temperature_tag,-1,length_tag,-1> heat_transfer_coefficient_t; Defining the unit was easier: const heat_transfer_coefficient_t watts_per_square_meter_per_celcis = watts / square_meter / kelvin; But this fails to compile, with this error: error: conversion from ‘boost::units::unit<boost::units::dimension_list<boost::units::dim<boost::units::mass_tag, boost::units::static_rational<1l, 1l> >, boost::units::dimension_list<boost::units::dim<boost::units::time_tag, boost::units::static_rational<-0x00000000000000003l, 1l> >, boost::units::dimension_list<boost::units::dim<boost::units::temperature_tag, boost::units::static_rational<-0x00000000000000001l, 1l> >, boost::units::dimensionless_type> > >, boost::units::homogeneous_system<boost::units::SI::system_tag> >’ to non-scalar type ‘boost::units::composite_dimension<boost::units::mass_tag, 1, boost::units::time_tag, -0x00000000000000003, boost::units::temperature_tag, -0x00000000000000001, boost::units::length_tag, -0x00000000000000001, boost::units::dimensionless_type, 0, boost::units::dimensionless_type, 0, boost::units::dimensionless_type, 0, boost::units::dimensionless_type, 0>’ requested Presumably this is because I have got something wrong in my working. I gave up at this point. For this library to be useful for me, it needs to be quick to learn and easy to apply. Working only with the included units it does look like it would work reasonably well, but in the situation I have described above it was quickly obvious that it was taking more effort to apply it to my program than the benefit that would result. There are two areas that I was interested in looking in more detail at, and I encourage other reviewers who get further than me to have a look at them: 1. What is the effect on compile time? I used #if to switch between units and plain floats. 2. Is there any increase in object file size? I know there shouldn't be, but it would be interesting to know for sure. 3. Are the error messages comprehensible? The one show above is not great, but it could have been worse; there are some Boost libraries which I find unusable because of the volumne and inpenetrability of the error messages that result from a simple typo (though the compiler must share the blame for this). Finally some random notes from my reading of the documentation: - "io" is a misnomer since it only does output, as far as I can see. - I tend to refer to temperature differences in Celcius, rather than Kelvin. There is an obvious issue when dealing with absolute temperatures though. - "Meter" vs. "Metre". My dictionary says "meter" is "chiefly U.S.". My physics books say "metre" consistently. Presumably both can be included. - Am I the only person who uses capital letters for units named after people? Hmm, maybe I am. - Please don't call the units used in the U.S. "English" units. Here in England, we use the S.I. system for everything except pints of beer and miles on roadsigns. The units that we did use here until about 50 years ago were not the same as the ones that the Americans use. I hope this helps. I will not express an opinion about whether the library should be included; I leave that to people who have made more progress with it. Phil.

AMDG Phil Endecott <spam_from_boost_dev <at> chezphil.org> writes:
I have spent a couple of hours looking at the units library. This is not a full review as I have not been able to compile my simple example in the time that I have available.
<snip>
so I concluded that the dimensions of power are mass length time^-3 and hence of heat transfer coefficient are mass time^-3 temperature^-1 length^-1, and wrote this:
typedef
composite_dimension<mass_tag,1,time_tag,-3,temperature_tag,-1,length_tag,-1>
heat_transfer_coefficient_t;
typedef unit< composite_dimension< mass_tag,1, time_tag,-3, temperature_tag,-1
::type, SI::system heat_transfer_coefficient_t;
or typedef divide_typeof_helper< divide_typeof_helper< SI::power, SI::temperature
::type, SI::area ::type heat_transfer_coefficient_t;
Defining the unit was easier:
const heat_transfer_coefficient_t watts_per_square_meter_per_celcis = watts / square_meter / kelvin;
But this fails to compile, with this error:
error: conversion from
<snip>
Presumably this is because I have got something wrong in my working. I gave up at this point.
For this library to be useful for me, it needs to be quick to learn and easy to apply. Working only with the included units it does look like it would work reasonably well, but in the situation I have described above it was quickly obvious that it was taking more effort to apply it to my program than the benefit that would result.
There are two areas that I was interested in looking in more detail at, and I encourage other reviewers who get further than me to have a look at them:
1. What is the effect on compile time? I used #if to switch between units and plain floats.
It depends on how many different units you are using.
2. Is there any increase in object file size? I know there shouldn't be, but it would be interesting to know for sure.
suppose you have a function template<class T> T f(const T&); Now, if you use float will only be instantiated once. If, on the other hand you use quantity f will be instantiated for every unit.
3. Are the error messages comprehensible? The one show above is not great, but it could have been worse; there are some Boost libraries which I find unusable because of the volumne and inpenetrability of the error messages that result from a simple typo (though the compiler must share the blame for this).
The main problem is that the types store a tremendous amount of information and therefore have very long names.
Finally some random notes from my reading of the documentation:
- "io" is a misnomer since it only does output, as far as I can see.
Uh. right.
- I tend to refer to temperature differences in Celcius, rather than Kelvin. There is an obvious issue when dealing with absolute temperatures though.
- "Meter" vs. "Metre". My dictionary says "meter" is "chiefly U.S.". My physics books say "metre" consistently. Presumably both can be included.
They are.
- Am I the only person who uses capital letters for units named after people? Hmm, maybe I am.
http://www.boost.org/more/lib_guide.htm#Design_and_Programming In Christ, Steven Watanabe

Phil, Thanks for taking a look.
The units of the heat transfer coefficient are W C^-1 m^-2. As far as I was able to see, I was not able to write anything like
typedef quantity<power/temperature/area> heat_transfer_coefficient_t;
If your compiler supports native typeof, you can just write this: typedef typeof(watts/kelvin/pow<2>(meter)) heat_transfer_coefficient_unit_type; typedef quantity<heat_transfer_coefficient_unit_type> heat_transfer_coefficient_t;
Rather, it was necessary for me to reduce W C^-1 m^-2 to basic dimensions manually. This is not easy for me. I have to remember phyics that I
If and when auto type deduction becomes a reality in C++, this will all become much simpler. For the meantime, you can either use the typeof trick above or you can compute the unit in a small test program like this : std::cout << watts/kelvin/pow<2>(meter) << std::endl; to get the units : kg s^(-3) K^(-1)
so I concluded that the dimensions of power are mass length time^-3 and hence of heat transfer coefficient are mass time^-3 temperature^-1 length^-1, and wrote this:
Congrats - you got it right. Here's a complete program that does what you want (to this point, anyway) : #include <iostream> #include <boost/units/io.hpp> #include <boost/units/unit.hpp> #include <boost/units/quantity.hpp> #include <boost/units/systems/si.hpp> using namespace boost::units; using namespace boost::units::SI; typedef quantity<power> power_t; typedef quantity<area> area_t; typedef quantity<temperature> temp_diff_t; typedef typeof(watts/kelvin/pow<2>(meter)) heat_transfer_coefficient_unit_type; typedef quantity<heat_transfer_coefficient_unit_type> heat_transfer_coefficient_t; int main() { const heat_transfer_coefficient_t watts_per_square_meter_per_kelvin = 1.0*watts/square_meter/kelvin; std::cout << heat_transfer_coefficient_unit_type() << std::endl << watts_per_square_meter_per_kelvin << std::endl << std::endl; return 0; } outputting kg s^(-3) K^(-1) 1 kg s^(-3) K^(-1)
typedef composite_dimension<mass_tag, 1,time_tag,-3,temperature_tag,-1,length_tag,-1> heat_transfer_coefficient_t;
This is the correct dimension. You need to associate it with a unit system to get a unit : typedef unit<heat_transfer_coefficient_t,SI::system> si_htc_unit_t;
Defining the unit was easier:
const heat_transfer_coefficient_t watts_per_square_meter_per_celcis = watts / square_meter / kelvin;
But this fails to compile, with this error:
<snip> You tried to assign a unit to a quantity; quantities can be expressed as value_type*unit, so what you want to do is const quantity<si_htc_unit_t> watts_per_square_meter_per_celcius = 7.4*watts/square_meter/kelvin;
For this library to be useful for me, it needs to be quick to learn and easy to apply. Working only with the included units it does look like it would work reasonably well, but in the situation I have described above it was quickly obvious that it was taking more effort to apply it to my program than the benefit that would result.
All I can say is that dimensional analysis and units is more complicated than it seems it ought to be... Compiler support for typeof and auto or emulation using Boost.Typeof goes a long way to simplify things. I am also happy to add more commonly used units to the library as they crop up...
1. What is the effect on compile time? I used #if to switch between units and plain floats.
Since the work is done with metaprogramming on lists, the overhead depends on how numerous and how complex the units used are. Steven's work on the implementation side has made, I believe, the compile times quite manageable for the examples we present, even those that use many different units.
2. Is there any increase in object file size? I know there shouldn't be, but it would be interesting to know for sure.
Steven seems to have addressed this.
3. Are the error messages comprehensible? The one show above is not great, but it could have been worse; there are some Boost libraries which I find unusable because of the volumne and inpenetrability of the error messages that result from a simple typo (though the compiler must share the blame for this).
We've done what we could to make error messages occur near the point of the actual error and be as reasonable as possible, but, as with most template metaprogramming code, errors can't really be described as terse. If you're doing a lot of programming with units, they begin to become easier to decipher...
- "io" is a misnomer since it only does output, as far as I can see.
Good point. We'll have to think of a better name, I guess...
- I tend to refer to temperature differences in Celcius, rather than Kelvin. There is an obvious issue when dealing with absolute temperatures though.
Take a look at unit_example_20 - this deals specifically with the absolute/relative temperature conversion issue...
- Please don't call the units used in the U.S. "English" units. Here in England, we use the S.I. system for everything except pints of beer and miles on roadsigns. The units that we did use here until about 50 years ago were not the same as the ones that the Americans use.
In boost/units/systems/other/non_si_units.hpp I have included conversion factors for Imperial units (the ones used in the recent past in England), US Customary units, US Survey units, nautical units, some non-SI metric units, etc... English units generally refer to heterogeneous and obsolete units, while Imperial and US Customary are the main non-SI systems still in some use... See here, also : http://en.wikipedia.org/wiki/English_unit
I hope this helps. I will not express an opinion about whether the library should be included; I leave that to people who have made more progress with it.
Thank you for your input and comments. If you do find some more time to work with it, I would certainly appreciate any additional input you might have. Matthias

AMDG Matthias Schabel <boost <at> schabel-family.org> writes:
- Please don't call the units used in the U.S. "English" units. Here in England, we use the S.I. system for everything except pints of beer and miles on roadsigns. The units that we did use here until about 50 years ago were not the same as the ones that the Americans use.
In boost/units/systems/other/non_si_units.hpp I have included conversion factors for Imperial units (the ones used in the recent past in England), US Customary units, US Survey units, nautical units, some non-SI metric units, etc... English units generally refer to heterogeneous and obsolete units, while Imperial and US Customary are the main non-SI systems still in some use... See here, also :
We could define the base units separately and then mix and match struct meter_tag : public ordinal<1> {}; struct foot_tag : public ordinal<2> {}; struct inch_tag : public ordinal<3> {}; struct yard_tag : public ordinal<4> {}; struct mile_tag : public ordinal<5> {}; struct gram_tag : public ordinal<6> {}; struct slug_tag : public ordinal<7> {}; struct second_tag : public ordinal<8> {}; struct minute_tag : public ordinal<9> {}; struct hour_tag : public ordinal<10> {}; struct ampere_tag : public ordinal<11> {}; struct biot_tag : public ordinal<12> {}; struct kelvin_tag : public ordinal<13> {}; struct mole_tag : public ordinal<14> {}; struct candela_tag : public ordinal<15> {}; struct radian_tag : public ordinal<16> {}; struct degree_tag : public ordinal<17> {}; struct gradian_tag : public ordinal<18> {}; struct steradian_tag : public ordinal<19> {}; // specializations of base_unit_converter and // unit_info namespace SI { typedef make_system< mpl::map< mpl::pair<length_tag, meter_tag>, mpl::pair<mass_tag, scaled_system<gram_tag, 1000> >, mpl::pair<time_tag, second_tag>, mpl::pair<current_tag, ampere_tag>, mpl::pair<temperature_tag, kelvin_tag>, mpl::pair<amount_tag, mole_tag>, mpl::pair<intensity_tag, candela_tag>, mpl::pair<angle_tag, radian_tag>, >
::type system_tag; }
Everything else in si/* remains the same make_system and scaled_system each take about 50 lines of code to implement. In Christ, Steven Watanabe

- "io" is a misnomer since it only does output, as far as I can see.
Actually, input is supported through the Boost.Serialization library - naturally, it only can verify that the stored object being read is consistent with the one being populated, but I guess that still sort of qualifies as input... Matthias

On 3/26/07, Phil Endecott <spam_from_boost_dev@chezphil.org> wrote:
- Please don't call the units used in the U.S. "English" units. Here in England, we use the S.I. system for everything except pints of beer and miles on roadsigns. The units that we did use here until about 50 years ago were not the same as the ones that the Americans use.
On that note, I have an (old) pocket handbook that says the following: The _British Unit of Length_ is the Imperial Standard Yard = the length of a bronze bar, preserved in the Parliament building in London at 62 degrees F. In 1935 1 in. was determined as equaling 25.399956mm and 1 yard as 0.914398416 m. The _North American Yard_, by the Mendenhall decree in 1893 was determined as equaling (3600/3937) m = 0.9144018 m; 1 American in. = 25.400051 mm. Wikipedia suggests that there's also an _International Yard_ = 0.9144 m; making 1 International inch = 25.4 mm. Glad to be using the metric system, ~ Scott McMurray

Scott McMurray wrote:
On that note, I have an (old) pocket handbook that says the following: The _British Unit of Length_ is the Imperial Standard Yard = the length of a bronze bar, preserved in the Parliament building in London at 62 degrees F. In 1935 1 in. was determined as equaling 25.399956mm and 1 yard as 0.914398416 m. The _North American Yard_, by the Mendenhall decree in 1893 was determined as equaling (3600/3937) m = 0.9144018 m; 1 American in. = 25.400051 mm.
Wikipedia suggests that there's also an _International Yard_ = 0.9144 m; making 1 International inch = 25.4 mm.
It /is/ an old handbook! Recently (in the '50s I think) the US and UK standardized on one inch = 25.4mm exactly. -- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

Phil,
simple awk script to do the arithmetic. If dimensional analysis had been available, it would have been a useful confidence builder that the code was doing the right thing. The problem was this: I have measured the temperatures on the surfaces of an electrical device - a power supply - and I want to calculate the power dissipated. The maths is simple: power = temperature difference to atmosphere * area * heat transfer coefficient. I tried to write this using the units library.
If you don't need to store the heat transfer coefficient, you can make this a one-liner without worrying about the type of the HTC itself (assuming you've defined quantities for dT and A already) : quantity<power> P = dT*A*7.5*watts/kelvin/square_meter; Matthias

Phil Endecott wrote:
- Am I the only person who uses capital letters for units named after people? Hmm, maybe I am. Probably not, but anybody who does for SI units is wrong :-). Units named after people are spelt with a lower case letter (eg newton, watt), but their symbol is an upper case letter (eg N, W).
- Please don't call the units used in the U.S. "English" units. Here in England, we use the S.I. system for everything except pints of beer and miles on roadsigns. a) You are on a loser here. The system is called "English" in the US (and there are more of them than there are of us). (For another example, the "English Muffin" is nothing like any item of food you can find in the UK.) b) The situation is /much/ more complex than that. I buy my petrol in litres, but still think in consumption in mpg. I measure carpentry in inches and mm depending on which gives the roundest number. I am just starting to weigh out 250g flour to make pastry rather than 8oz. I have posted to a newsgroup "How much rock for a rockery on a slope two feet high, 12.5 metres long?".
The units that we did use here until about 50 years ago The change is much more recent than that. We were taught SI in science 30 years ago, but almost everything was done in Imperial. My son on the other hand, can barely visualize an inch. were not the same as the ones that the Americans use. It's only the volume that is different (afaik).
-- Martin Bonner Project Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Martin Bonner Sent: 27 March 2007 09:38 To: boost@lists.boost.org Subject: Re: [boost] Units: brief review
- Please don't call the units used in the U.S. "English" units.
The system is called "English" in the US
Isn't the right term "Imperial"? Even if Non-PC! But you are right it is US gallons that different from Imperial gallons. But in England we do buy petrol in liters, mainly because the price displays only go up to 99p, and gallons long ago cost more than £1. And we buy gas in cylinders ;-) Mad! But there you go.... Paul --- Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539561830 & SMS, Mobile +44 7714 330204 & SMS pbristow@hetp.u-net.com
participants (6)
-
Martin Bonner
-
Matthias Schabel
-
me22
-
Paul A Bristow
-
Phil Endecott
-
Steven Watanabe