[Units] Units in unit tests

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[Units] Units in unit tests

Boost - Users mailing list
Hello all,

please excuse the weird subject line. I have just introduced boost units as length quantity for vectors into my project here.

What previously was:

typedef boost::qvm::vec<double, 3>     vec3;

is now:

typedef boost::units::quantity<length, double> qlength;
typedef boost::qvm::vec<qlength, 3>     vec3;

Which seems to work OK so far, I'm not done testing. While converting all my unit tests I came to wonder is how this is best adopted.

I have lots of lines like:

vec3 v = get_some_value();

and then I test the individual component values like this:
BOOST_CHECK_CLOSE(X(v), 42.0, 0.001);    // check for length of 42 meters

Now this would have to be rewritten to:

BOOST_CHECK_CLOSE(X(v).value(), 42.0, 0.001);

But doing this, I imply the length is in meters, right? Doesn't that defeat the purpose a little? I feel this would be better:

BOOST_CHECK_CLOSE(X(v), 42.0 * meters, 0.001);

but the Macro won't accept this as this is not a floating point type anymore. 
Does anybody have some hint as to how this is best addressed while still have maximum readability?

All my best...
Stephan

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units] Units in unit tests

Boost - Users mailing list
On 8/05/2017 02:08, Stephan Menzel wrote:

> I have lots of lines like:
>
> vec3 v = get_some_value();
>
> and then I test the individual component values like this:
> BOOST_CHECK_CLOSE(X(v), 42.0, 0.001);    // check for length of 42 meters
>
> Now this would have to be rewritten to:
>
> BOOST_CHECK_CLOSE(X(v).value(), 42.0, 0.001);
>
> But doing this, I imply the length is in meters, right? Doesn't that
> defeat the purpose a little? I feel this would be better:
>
> BOOST_CHECK_CLOSE(X(v), 42.0 * meters, 0.001);
>
> but the Macro won't accept this as this is not a floating point type
> anymore.
> Does anybody have some hint as to how this is best addressed while still
> have maximum readability?

I don't know if there is a better way to do this within the confines of
Boost.Test itself (perhaps making a custom macro, or extending what the
macro already does in some way), but there *is* a better way to get
basic values out of unit quantities rather than using .value().

Instead of:

BOOST_CHECK_CLOSE(X(v).value(), 42.0, 0.001);

Try:

BOOST_CHECK_CLOSE(X(v) / meters, 42.0, 0.001);

(You might also need an explicit static_cast<double>.  If so, you might
want to wrap this whole thing in a helper method to reduce typing.)

This explicitly specifies what unit and scale you want the comparison to
be performed in -- and you can for example request a comparison in
millimeters or inches if you use the appropriate definitions.  And it
won't compile if you use the wrong dimension -- eg. if you try to
extract seconds from a length measurement.


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units] Units in unit tests

Boost - Users mailing list
Hello Gavin,

thanks for your response.

On Mon, May 8, 2017 at 4:17 AM, Gavin Lambert via Boost-users <[hidden email]> wrote:

I don't know if there is a better way to do this within the confines of Boost.Test itself (perhaps making a custom macro, or extending what the macro already does in some way),

I was suspecting this, just wanted to clarify. I guess I will create my own wrappers then.

 
but there *is* a better way to get basic values out of unit quantities rather than using .value().

Instead of:

BOOST_CHECK_CLOSE(X(v).value(), 42.0, 0.001);

Try:

BOOST_CHECK_CLOSE(X(v) / meters, 42.0, 0.001);

(You might also need an explicit static_cast<double>.  If so, you might want to wrap this whole thing in a helper method to reduce typing.)

OK, this is a bit of surprise. This "X(v) / meters" obviously means "I want the value in meters"?
Actually I spent quite some time trying to figure that exact thing out and I just couldn't find it in the docs. I have just tried it and it works.

Great, that's at least a way to make things explicit and helps.

Thanks,
Stephan


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units] Units in unit tests

Boost - Users mailing list
AMDG

On 05/08/2017 01:11 AM, Stephan Menzel via Boost-users wrote:

>
> On Mon, May 8, 2017 at 4:17 AM, Gavin Lambert via Boost-users <
> [hidden email]> wrote:
>
>>
>> Try:
>>
>> BOOST_CHECK_CLOSE(X(v) / meters, 42.0, 0.001);
>>
>> (You might also need an explicit static_cast<double>.  If so, you might
>> want to wrap this whole thing in a helper method to reduce typing.)
>>
>
> OK, this is a bit of surprise. This "X(v) / meters" obviously means "I want
> the value in meters"?
> Actually I spent quite some time trying to figure that exact thing out and
> I just couldn't find it in the docs. I have just tried it and it works.
>

The meaning is literally division.  (1.0 * meters) / meters = 1.0
If the expression exactly cancels out all units, then the
result is dimensionless and can be implicitly converted
to a double.

> Great, that's at least a way to make things explicit and helps.
>

In Christ,
Steven Watanabe

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units] Units in unit tests

Boost - Users mailing list
Hello Steven,

thanks for your great work on Units!

On Mon, May 8, 2017 at 3:11 PM, Steven Watanabe via Boost-users <[hidden email]> wrote:

The meaning is literally division.  (1.0 * meters) / meters = 1.0
If the expression exactly cancels out all units, then the
result is dimensionless and can be implicitly converted
to a double.

OK, I see. From my perspective, having never used Units this was not quite intuitive if you don't mind me say so. If you would allow me to get a little off topic....

My reason behind switching to units was that I wanted to get rid of implicit assumptions about what unit a quantity is in. I am in a client / server environment and store such vectors coming from a client that uses centimeters as all units. Now I expect further clients and want to be prepared for them to use other units, say millimeters. By using Units I intend to push that translation to the foremost interface of the system and not translate anything behind that. 

I have much appreciated the constructor of quantity and the fact that it fails to compile without a unit to give meaning to a scalar. This is an excellent design paradigm and will help eliminate bugs!

qlength q(42.0 * meters);

Nice.

My problem that led to the above misconception was, that I needed to translate that back and forth to the client. From the client was quite easy: 

qlength q(4200.0 * centi*meters);

Looks good enough. But getting the value back in centimeters was not. I tried:

double raw_value_to_send_back = q / centi*meters;

But this won't compile. So I looked into scaled units and typedefed this:

typedef boost::units::make_scaled_unit<
boost::units::si::length, 
boost::units::scale<10, boost::units::static_rational<-2> > >::type centimeters;

And now I can convert into centimers like this:

double raw_value_to_send_back = quantity<centimeters, double>(n_value).value();

But still, I'm not sure I am using it as intended. Is this the best and easiest way to handle such things or am I mistaken and q / centi*meters really is supposed to work?

Best regards...

Stephan


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Units] Units in unit tests

Boost - Users mailing list
AMDG

On 05/08/2017 07:30 AM, Stephan Menzel via Boost-users wrote:

> Hello Steven,
>
> thanks for your great work on Units!
>
> On Mon, May 8, 2017 at 3:11 PM, Steven Watanabe via Boost-users <
> [hidden email]> wrote:
>>
>>
>> The meaning is literally division.  (1.0 * meters) / meters = 1.0
>> If the expression exactly cancels out all units, then the
>> result is dimensionless and can be implicitly converted
>> to a double.
>>
>
> OK, I see. From my perspective, having never used Units this was not quite
> intuitive if you don't mind me say so. If you would allow me to get a
> little off topic....
>

  This trick wasn't really a part of the library
design.  We originally intended that the primary
way to access the raw value would be though q.value()
or quantity_cast<double>(q).  Using q / meters falls
out naturally from the definition of division, though.

> <snip>
> Looks good enough. But getting the value back in centimeters was not. I
> tried:
>
> double raw_value_to_send_back = q / centi*meters;
>
> But this won't compile. So I looked into scaled units and typedefed this:
>
> typedef boost::units::make_scaled_unit<
> boost::units::si::length,
> boost::units::scale<10, boost::units::static_rational<-2> > >::type
> centimeters;
>
> And now I can convert into centimers like this:
>
> double raw_value_to_send_back = quantity<centimeters,
> double>(n_value).value();
>
> But still, I'm not sure I am using it as intended.

  Yes.  Casting to centimeters and then extracting
the value is one way to do this.

> Is this the best and
> easiest way to handle such things or am I mistaken and q / centi*meters
> really is supposed to work?
>

  q / centi*meters is parsed as (q/centi)*meters, which
is not what you intend.  Ideally, static_cast<double>(q/(centi*meters))
would work, but implementing that requires C++11 (explicit
conversion operators) and Units was originally written in 2006.
static_cast<quantity<dimensionless>>(q/(centi*meters)) should work now.

In Christ,
Steven Watanabe

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users