Modify

Opened 3 years ago

Closed 3 weeks ago

Last modified 3 weeks 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>

Attachments (0)

Change History (9)

comment:1 Changed 3 years ago by bnorman@…

I'm hung up on exactly the same problem.

comment:2 in reply to:  1 Changed 3 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 3 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 3 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 3 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 3 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 2 years ago by anonymous

The bug persists

comment:8 Changed 8 months ago by anonymous

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

comment:9 Changed 3 weeks ago by Jürgen Hunold

Resolution: fixed
Status: newclosed
Version: Boost 1.55.0Boost Development Trunk
Last edited 3 weeks ago by Jürgen Hunold (previous) (diff)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Matthias Schabel.
The resolution will be deleted.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.