Opened 4 years ago

Closed 10 months ago

Last modified 10 months ago

#10270 closed Bugs (fixed)

square root of boost units scaled_unit fails to compile

Reported by: sharifmarat@… Owned by: Matthias Schabel
Milestone: To Be Determined Component: units
Version: Boost Development Trunk Severity: Problem
Keywords: scale Cc:

Description

I have created a scaled unit to handle micro meters:

typedef make_scaled_unit<si::length,
                         scale<10, static_rational<-6> > >::type micro_meter_unit;

Everything works as expected:

quantity<si::length, double> some_meter = 10 * si::meter;
quantity<micro_meter_unit, double> some_mu_meter = 
  static_cast<quantity<micro_meter_unit, double>>(some_meter);

std::cout << "some_meter^2 = " << some_meter * some_meter;  // outputs 100 m^2
std::cout << "some_mu_meter^2 = " << some_mu_meter * some_mu_meter; // outputs 1e+014 p(m^2)

Yet the square root operations is not compiled:

std::cout << "sqrt(some_meter) = " << sqrt(some_meter); // outputs 3.16228 m^(1/2)
std::cout << "sqrt(some_mu_meter) = " << sqrt(some_mu_meter); //error here
// 'value' : is not a member of 'boost::units::scale_dim_tag'

Also the following code fails to compile:

quantity<si::length, double> mu_meter(sqrt(1.0 * si::micro * si::meter * si::meter));

I used the following include files:

#include <iostream>
#include <boost/units/quantity.hpp>
#include <boost/units/make_scaled_unit.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/cmath.hpp>
#include <boost/units/io.hpp>
#include <boost/units/scale.hpp>
#include <boost/units/systems/si/prefixes.hpp>

Change History (9)

comment:1 Changed 4 years ago by bnorman@…

I'm hung up on exactly the same problem.

comment:2 in reply to:  1 Changed 4 years ago by bnorman@…

Replying to bnorman@…:

I'm hung up on exactly the same problem.

FYI, I am now able to work around this issue as follows:

typedef scaled_base_unit<si::meter_base_unit,
                         scale<10, static_rational<-6> > >::type micro_meter_base_unit;
typedef micro_meter_base_unit::unit_type micro_meter_unit;

comment:3 Changed 4 years ago by Wouter Boomsma <wb@…>

I'm stuck with the same problem. Is there any hope for a fix in the near future? It would really be greatly appreciated.

As far as I can see, the suggested work-around does not work in my case, since the scaled unit is not a base unit. In my application, I need a kilojoule unit. The obvious approach would be:

typedef make_scaled_unit<si::energy, scale<10, static_rational<3> > >::type energy_unit_kJ;

However, if this unit is involved in any nontrivial calculations involving sqrt or pow, it fails as described above.

The scaled_base_unit workaround suggested by bnorman does not work directly since joule is not a base unit. Instead, I attempted to define a base unit from scratch, and set up the conversion factory manually:

struct energy_base_unit_kJ: base_unit<energy_base_unit_kJ, energy_dimension, 1> {

static std::string name() {return "kilojoule";}

static std::string symbol() { return "kJ"; }

};

BOOST_UNITS_DEFINE_CONVERSION_FACTOR(

energy_base_unit_kJ, si::energy, double, 1/1000.0);

The problem is that I cannot define the reverse conversion factor because si::energy is not a base unit, and BOOST_UNITS_DEFINE_CONVERSION_FACTOR requires its first argument to be a base unit.

If there is some clever way to work around this, I would appreciate a pointer in the right direction - but under all circumstances, it would really be convenient if make_scaled_unit just worked.

comment:4 Changed 4 years ago by petamas@…

Hi all, here's a fix for this problem:

namespace boost
{
  namespace mpl
  {
    template<>
    struct divides_impl<boost::units::scale_dim_tag,boost::units::detail::static_rational_tag>
    {
      template<class T0, class T1>
      struct apply
      {
        typedef boost::units::scale_list_dim<
          boost::units::scale<
            (T0::base),
            typename mpl::divides<typename T0::exponent, T1>::type
          >
        > type;
      };
    };
  }
}

The main problem is that boost::mpl::divides does not work for a scale_list_dim and a static_rational. Power works because boost::mpl::times is implemented in boost/units/detail/unscale.hpp. (In fact, my fix is the copy of that code, replacing "times" with "divides".)

I'll try to add the fix to the library, but it's my first time on boost trac, so I don't know how long that'll take.

comment:5 Changed 4 years ago by Wouter Boomsma <wb@…>

Thanks! It would be greatly appreciated if you could submit this fix to Boost trunk.

comment:6 in reply to:  5 Changed 4 years ago by Tamas Peregi <petamas@…>

Replying to Wouter Boomsma <wb@…>:

Thanks! It would be greatly appreciated if you could submit this fix to Boost trunk.

I'll try, I hope I'll have time to look into submitting on the weekend.

comment:7 Changed 3 years ago by anonymous

The bug persists

comment:8 Changed 17 months ago by anonymous

The bug persists. Patch by "petamas" fixes compilation problem. Thanks a lot!

comment:9 Changed 10 months ago by Jürgen Hunold

Resolution: fixed
Status: newclosed
Version: Boost 1.55.0Boost Development Trunk
Last edited 10 months ago by Jürgen Hunold (previous) (diff)
Note: See TracTickets for help on using tickets.