Boost Units initialize quantity with signaling NaN
Hi, I’m trying to find a way to initialize a Boost Unit with a signaling NaN, not just a NaN with the signal cleared. It seems that the only way to initialize a quantity is by multiplying by the unit, and that multiplication clears the signal on the NaN. I know I can just modify the quantity.hpp header and initialize the default constructor val_ member with the signaling NaN, but I was hoping for a cleaner solution. Here’s an example (typed in by hand, not tested): const double s_nan = std::numeric_limits<double>::signaling_NaN(); typedef quantity<si::acceleration, double> acceleration_t; BOOST_UNITS_STATIC_CONSTANT(acceleration_u, acceleration); acceleration_t a(s_nan * acceleration_u); // <— this clears the signal on the NaN Has anyone encountered this or know of a more elegant solution than modifying the quantity.hpp header? — Noel
On Aug 10, 2016, at 8:55 PM, Belcourt, Kenneth <kbelco@sandia.gov> wrote:
I’m trying to find a way to initialize a Boost Unit with a signaling NaN, not just a NaN with the signal cleared. It seems that the only way to initialize a quantity is by multiplying by the unit, and that multiplication clears the signal on the NaN. I know I can just modify the quantity.hpp header and initialize the default constructor val_ member with the signaling NaN, but I was hoping for a cleaner solution.
Here’s an example (typed in by hand, not tested):
const double s_nan = std::numeric_limits<double>::signaling_NaN();
typedef quantity<si::acceleration, double> acceleration_t; BOOST_UNITS_STATIC_CONSTANT(acceleration_u, acceleration);
acceleration_t a(s_nan * acceleration_u); // <— this clears the signal on the NaN
A little more info about this problem. We have customers with Boost installs that we can’t modify (i.e. we can’t copy quantity.hpp into their Boost install) and we can’t ship a copy of Boost because building Boost MPI for our customer’s system is quite complicated. We use this signaling nan technique when our customers report problems running our codes. This requires me to find a way to enable the signaling NaN in quantity.hpp when those customers report having problems. We’d like to (1) use a macro to enable signaling nan initialization in quantity.hpp and (2) detect if our customer’s Boost install doesn’t support this signaling nan macro. The attached test case demonstrates one way to support these two use cases (test case runs on MBP). Would there be any interest in trying to add this capability to Boost Units? — Noel
AMDG On 08/10/2016 08:55 PM, Belcourt, Kenneth wrote:
I’m trying to find a way to initialize a Boost Unit with a signaling NaN, not just a NaN with the signal cleared. It seems that the only way to initialize a quantity is by multiplying by the unit, and that multiplication clears the signal on the NaN. I know I can just modify the quantity.hpp header and initialize the default constructor val_ member with the signaling NaN, but I was hoping for a cleaner solution.
Here’s an example (typed in by hand, not tested):
const double s_nan = std::numeric_limits<double>::signaling_NaN();
typedef quantity<si::acceleration, double> acceleration_t; BOOST_UNITS_STATIC_CONSTANT(acceleration_u, acceleration);
acceleration_t a(s_nan * acceleration_u); // <— this clears the signal on the NaN
Has anyone encountered this or know of a more elegant solution than modifying the quantity.hpp header?
I can't reproduce the problem with VS 2015. #include <boost/units/quantity.hpp> #include <limits> #include <boost/units/systems/si.hpp> #include <iostream> using boost::units::quantity; namespace si = boost::units::si; int main() { quantity<si::length> x(std::numeric_limits<double>::signaling_NaN() * si::meter); std::cout << std::hex << *(unsigned long long*)&x << std::endl; return 0; } prints 7ff8000000000001 Multiplication by a unit (as opposed to a quantity) does not require a floating point multiplication. It only copies the value around. I have no idea why you're seeing the signal bit being cleared. In Christ, Steven Watanabe
On Aug 13, 2016, at 10:56 AM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
On 08/10/2016 08:55 PM, Belcourt, Kenneth wrote:
I’m trying to find a way to initialize a Boost Unit with a signaling NaN, not just a NaN with the signal cleared. It seems that the only way to initialize a quantity is by multiplying by the unit, and that multiplication clears the signal on the NaN. I know I can just modify the quantity.hpp header and initialize the default constructor val_ member with the signaling NaN, but I was hoping for a cleaner solution.
Here’s an example (typed in by hand, not tested):
const double s_nan = std::numeric_limits<double>::signaling_NaN();
typedef quantity<si::acceleration, double> acceleration_t; BOOST_UNITS_STATIC_CONSTANT(acceleration_u, acceleration);
acceleration_t a(s_nan * acceleration_u); // <— this clears the signal on the NaN
Has anyone encountered this or know of a more elegant solution than modifying the quantity.hpp header?
I can't reproduce the problem with VS 2015.
#include <boost/units/quantity.hpp> #include <limits> #include <boost/units/systems/si.hpp> #include <iostream>
using boost::units::quantity; namespace si = boost::units::si;
int main() { quantity<si::length> x(std::numeric_limits<double>::signaling_NaN() * si::meter); std::cout << std::hex << *(unsigned long long*)&x << std::endl; return 0; }
prints 7ff8000000000001
Multiplication by a unit (as opposed to a quantity) does not require a floating point multiplication. It only copies the value around. I have no idea why you're seeing the signal bit being cleared.
I wonder if copying is somehow causing problems. I see this: Copying a NaN may not preserve its bit representation. mentioned here: http://en.cppreference.com/w/cpp/types/numeric_limits/signaling_NaN Perhaps that’s our problem. Thanks for the help Steven.
participants (2)
-
Belcourt, Kenneth
-
Steven Watanabe