Boost logo

Boost :

From: Matthias Schabel (boost_at_[hidden])
Date: 2003-12-15 02:13:48


> The dimension test now produces unmangled (and plausible but verbose!)
> output
> OK.

At some point I may write a little MPL demangler to simplify the output
further to make it more comprehensible.

> Compile time 20 sec on my 700 Mhz Athlon, so perhaps 5 sec on a new
> machine?
> which is worryingly long. However, perhaps in practice this will not
> increase
> for more real-life code?

I have been focusing on correctness rather than compile-time
efficiency. I'm already aware that there are several core algorithms
which are n^2 efficiency (where n is the length of the dimension tag
list) when they should probably be log n - I will work on this at some
point, but since it's an implementation detail, I'd rather get some
consensus on the interface and design before spending too much time
performance tuning. I also suspect that future compilers will become
more efficient in dealing with template metaprogramming as the whole
concept is still relatively new and hasn't seen widespread
application... The time overhead will basically depend on the number
of different units and combinations thereof which appear in a program,
so in large programs in which only a few different units appear it will
probably already be insignificant.

> Test_units fails to compile (after 30 sec) :

Compilation is slow for test_units.cpp under GCC - probably ~30sec.
The compile time error looks to me like a bug from an old header that
somehow crept back into the code. I've posted a corrected version
which fixes the problem.

> #ifdef _MSC_VER
> # pragma warning(disable: 4511) // copy constructor could not be
> generated

Can you remind me - do pragmas apply only to the file in which they
appear or do they propagate? I'm assuming the former, and have pasted
these into the test programs, but if the latter I could move them to
one of the root-level headers. Ultimately, I'd like to track down
these warnings and see about making them go away, assuming that they're
not completely spurious or otherwise incorrect.

As far as astronomical unit systems go, I only really know of
astronomical distances so I'll do an example setting up two models, one
with light years and another with parsecs and make them convertible
using light years as the model for conversions? The basic procedure
for creating a full-fledged new system of physical units is to take
cgs_units.hpp as a template, create a new model for the system you want
to define like this :

struct SomeNewModel : public PhysicalUnitModel<SomeNewModel> { };

Then define the UnitInfo specializations for the dimension tags,
specifying the conversion factor to equivalent SI units in the template
member function toBase and the desired unit symbol and abbreviation in
symbol() and abbreviation() respectively. Named units can be put in a
namespace for convenience - these are base or derived units with no
scale factors within the new model.

Here's a walkthrough of the astronomical distance case for distances
only (found in test_ly_pc.cpp) :

#include <iostream>

#include <mcs/units/dimensioned_io.hpp>
#include <mcs/units/physical_units.hpp>

using namespace mcs;
using namespace mcs::units;

namespace mcs {

namespace units {

// define light year model which specifies a length unit only
struct LightYearModel
{
     // length_type is defined in physical_units.hpp
     typedef DimensionedUnit<LightYearModel,length_type> length_unit;
};

// specialize UnitInfo to supply symbol, abbreviation, and conversion
factor information
// light years are converted using light years as the base unit for the
conversion
template<>
struct UnitInfo<LightYearModel,length_tag>
{
     typedef LightYearModel base_type;

        static std::string symbol() { return "light year"; }
        static std::string abbreviation() { return "ly"; }
        
        template<typename Y> static Y toBase() { return Y(1); }
};

// some constants for convenience
static const LightYearModel::length_unit _light_year,
                                             _light_years;

// a light year typedef for convenience
typedef DimensionedQuantity<double,LightYearModel::length_unit>
LightYear;

// do the same for parsecs
struct ParsecModel
{
     typedef DimensionedUnit<ParsecModel,length_type> length_unit;
};

template<>
struct UnitInfo<ParsecModel,length_tag>
{
     // allow conversions using light years as base distance
     typedef LightYearModel base_type;

        static std::string symbol() { return "parsec"; }
        static std::string abbreviation() { return "pc"; }
        
        // define conversion from parsec to light year
        template<typename Y> static Y toBase() { return Y(3.262); }
};

static const ParsecModel::length_unit _parsec,
                                         _parsecs;

typedef DimensionedQuantity<double,ParsecModel::length_unit> Parsec;

} // namespace units

} // namespace mcs

int main()
{
     LightYear d1(3.262*_light_years);

     Parsec d2(1.0*_parsec),
                 d3(d1);

     std::cout << d1 << std::endl
               << d2 << std::endl
               << d3 << std::endl
               << std::endl;

     return 0;
}

Note that this code doesn't depend at all on SI units - everything is
defined in a self-contained way. I will probably macro-ify the
UnitInfo definition to simplify this further. I've also got some
minimal documentation forthcoming in the next while...

Matthias

------------------------------------------------------------------------
---------------------------
Matthias Schabel, Ph.D.
Utah Center for Advanced Imaging Research
729 Arapeen Drive
Salt Lake City, UT 84108
801-587-9413 (work)
801-585-3592 (fax)
801-706-5760 (cell)
801-484-0811 (home)
mschabel at ucair med utah edu


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