mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 05:07:58 +00:00
bug-fix: handling of special values in ctor and in value method #301
* Fixed: Passing nan to the ctor of axis::variable failed to throw std::invalid_argument * Fixed: axis::variable{{0, 1, inf}}.value(1) was nan, because interpolation would compute 0 * inf
This commit is contained in:
parent
91e32ce17c
commit
ebe9010db8
@ -87,9 +87,9 @@ public:
|
|||||||
vec_.reserve(std::distance(begin, end));
|
vec_.reserve(std::distance(begin, end));
|
||||||
vec_.emplace_back(*begin++);
|
vec_.emplace_back(*begin++);
|
||||||
bool strictly_ascending = true;
|
bool strictly_ascending = true;
|
||||||
while (begin != end) {
|
for (; begin != end; ++begin) {
|
||||||
if (*begin <= vec_.back()) strictly_ascending = false;
|
strictly_ascending &= vec_.back() < *begin;
|
||||||
vec_.emplace_back(*begin++);
|
vec_.emplace_back(*begin);
|
||||||
}
|
}
|
||||||
if (!strictly_ascending)
|
if (!strictly_ascending)
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
@ -175,7 +175,8 @@ public:
|
|||||||
if (i > size()) return detail::highest<value_type>();
|
if (i > size()) return detail::highest<value_type>();
|
||||||
const auto k = static_cast<index_type>(i); // precond: i >= 0
|
const auto k = static_cast<index_type>(i); // precond: i >= 0
|
||||||
const real_index_type z = i - k;
|
const real_index_type z = i - k;
|
||||||
return (1.0 - z) * vec_[k] + z * vec_[k + 1];
|
// check z == 0 needed to avoid returning nan when vec_[k + 1] is infinity
|
||||||
|
return (1.0 - z) * vec_[k] + (z == 0 ? 0 : z * vec_[k + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return bin for index argument.
|
/// Return bin for index argument.
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
using namespace boost::histogram;
|
using namespace boost::histogram;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
constexpr auto inf = std::numeric_limits<double>::infinity();
|
||||||
|
constexpr auto nan = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
|
||||||
BOOST_TEST(std::is_nothrow_move_assignable<axis::variable<>>::value);
|
BOOST_TEST(std::is_nothrow_move_assignable<axis::variable<>>::value);
|
||||||
BOOST_TEST(std::is_nothrow_move_constructible<axis::variable<>>::value);
|
BOOST_TEST(std::is_nothrow_move_constructible<axis::variable<>>::value);
|
||||||
|
|
||||||
@ -29,6 +32,10 @@ int main() {
|
|||||||
BOOST_TEST_THROWS(axis::variable<>({1.0}), std::invalid_argument);
|
BOOST_TEST_THROWS(axis::variable<>({1.0}), std::invalid_argument);
|
||||||
BOOST_TEST_THROWS(axis::variable<>({1.0, 1.0}), std::invalid_argument);
|
BOOST_TEST_THROWS(axis::variable<>({1.0, 1.0}), std::invalid_argument);
|
||||||
BOOST_TEST_THROWS(axis::variable<>({1.0, -1.0}), std::invalid_argument);
|
BOOST_TEST_THROWS(axis::variable<>({1.0, -1.0}), std::invalid_argument);
|
||||||
|
BOOST_TEST_THROWS((axis::variable<>{{1.0, 2.0, nan}}), std::invalid_argument);
|
||||||
|
BOOST_TEST_THROWS((axis::variable<>{{1.0, nan, 2.0}}), std::invalid_argument);
|
||||||
|
BOOST_TEST_THROWS((axis::variable<>{{nan, 1.0, 2.0}}), std::invalid_argument);
|
||||||
|
BOOST_TEST_THROWS((axis::variable<>{{inf, inf}}), std::invalid_argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
// axis::variable
|
// axis::variable
|
||||||
@ -39,8 +46,8 @@ int main() {
|
|||||||
BOOST_TEST_EQ(static_cast<const axis::variable<>&>(a).metadata(), "foo");
|
BOOST_TEST_EQ(static_cast<const axis::variable<>&>(a).metadata(), "foo");
|
||||||
a.metadata() = "bar";
|
a.metadata() = "bar";
|
||||||
BOOST_TEST_EQ(static_cast<const axis::variable<>&>(a).metadata(), "bar");
|
BOOST_TEST_EQ(static_cast<const axis::variable<>&>(a).metadata(), "bar");
|
||||||
BOOST_TEST_EQ(a.bin(-1).lower(), -std::numeric_limits<double>::infinity());
|
BOOST_TEST_EQ(a.bin(-1).lower(), -inf);
|
||||||
BOOST_TEST_EQ(a.bin(a.size()).upper(), std::numeric_limits<double>::infinity());
|
BOOST_TEST_EQ(a.bin(a.size()).upper(), inf);
|
||||||
BOOST_TEST_EQ(a.value(0), -1);
|
BOOST_TEST_EQ(a.value(0), -1);
|
||||||
BOOST_TEST_EQ(a.value(0.5), -0.5);
|
BOOST_TEST_EQ(a.value(0.5), -0.5);
|
||||||
BOOST_TEST_EQ(a.value(1), 0);
|
BOOST_TEST_EQ(a.value(1), 0);
|
||||||
@ -51,9 +58,9 @@ int main() {
|
|||||||
BOOST_TEST_EQ(a.index(0), 1);
|
BOOST_TEST_EQ(a.index(0), 1);
|
||||||
BOOST_TEST_EQ(a.index(1), 2);
|
BOOST_TEST_EQ(a.index(1), 2);
|
||||||
BOOST_TEST_EQ(a.index(10), 2);
|
BOOST_TEST_EQ(a.index(10), 2);
|
||||||
BOOST_TEST_EQ(a.index(-std::numeric_limits<double>::infinity()), -1);
|
BOOST_TEST_EQ(a.index(-inf), -1);
|
||||||
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::infinity()), 2);
|
BOOST_TEST_EQ(a.index(inf), 2);
|
||||||
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::quiet_NaN()), 2);
|
BOOST_TEST_EQ(a.index(nan), 2);
|
||||||
|
|
||||||
BOOST_TEST_EQ(str(a),
|
BOOST_TEST_EQ(str(a),
|
||||||
"variable(-1, 0, 1, metadata=\"bar\", options=underflow | overflow)");
|
"variable(-1, 0, 1, metadata=\"bar\", options=underflow | overflow)");
|
||||||
@ -72,6 +79,29 @@ int main() {
|
|||||||
BOOST_TEST_NE(a, e);
|
BOOST_TEST_NE(a, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// infinity values in constructor
|
||||||
|
{
|
||||||
|
axis::variable<> a{{-inf, 1.0, 2.0, inf}};
|
||||||
|
BOOST_TEST_EQ(a.index(-inf), 0);
|
||||||
|
BOOST_TEST_EQ(a.index(0.0), 0);
|
||||||
|
BOOST_TEST_EQ(a.index(1.0), 1);
|
||||||
|
BOOST_TEST_EQ(a.index(2.0), 2);
|
||||||
|
BOOST_TEST_EQ(a.index(inf), 3);
|
||||||
|
|
||||||
|
BOOST_TEST_EQ(a.value(-1), -inf);
|
||||||
|
BOOST_TEST_EQ(a.value(-0.5), -inf);
|
||||||
|
BOOST_TEST_EQ(a.value(0), -inf);
|
||||||
|
BOOST_TEST_EQ(a.value(0.5), -inf);
|
||||||
|
BOOST_TEST_EQ(a.value(1), 1.0);
|
||||||
|
BOOST_TEST_EQ(a.value(1.5), 1.5);
|
||||||
|
BOOST_TEST_EQ(a.value(2), 2.0);
|
||||||
|
BOOST_TEST_EQ(a.value(2.5), inf);
|
||||||
|
BOOST_TEST_EQ(a.value(3), inf);
|
||||||
|
BOOST_TEST_EQ(a.value(4), inf);
|
||||||
|
|
||||||
|
BOOST_TEST_EQ(str(a), "variable(-inf, 1, 2, inf, options=underflow | overflow)");
|
||||||
|
}
|
||||||
|
|
||||||
// axis::variable circular
|
// axis::variable circular
|
||||||
{
|
{
|
||||||
axis::variable<double, axis::null_type, axis::option::circular_t> a{-1, 1, 2};
|
axis::variable<double, axis::null_type, axis::option::circular_t> a{-1, 1, 2};
|
||||||
@ -114,9 +144,9 @@ int main() {
|
|||||||
BOOST_TEST_EQ(a.size(), 5);
|
BOOST_TEST_EQ(a.size(), 5);
|
||||||
BOOST_TEST_IS_CLOSE(a.value(0), -10, 1e-9);
|
BOOST_TEST_IS_CLOSE(a.value(0), -10, 1e-9);
|
||||||
|
|
||||||
BOOST_TEST_EQ(a.update(-std::numeric_limits<double>::infinity()), pii_t(-1, 0));
|
BOOST_TEST_EQ(a.update(-inf), pii_t(-1, 0));
|
||||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::infinity()), pii_t(a.size(), 0));
|
BOOST_TEST_EQ(a.update(inf), pii_t(a.size(), 0));
|
||||||
BOOST_TEST_EQ(a.update(std::numeric_limits<double>::quiet_NaN()), pii_t(a.size(), 0));
|
BOOST_TEST_EQ(a.update(nan), pii_t(a.size(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterators
|
// iterators
|
||||||
|
Loading…
x
Reference in New Issue
Block a user