Skip to content

Commit 9009366

Browse files
authored
[ML] Trap potential cause of SIGFPE (#1351)
1 parent c00e4b6 commit 9009366

File tree

3 files changed

+25
-22
lines changed

3 files changed

+25
-22
lines changed

docs/CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
=== Bug Fixes
7373

7474
* Better interrupt handling during named pipe connection. (See {ml-pull}1311[#1311].)
75+
* Trap potential cause of SIGFPE. (See {ml-pull}1351[#1351], issue: {ml-issue}1348[#1348].)
7576

7677
== {es} version 7.8.0
7778

include/maths/CIntegerTools.h

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,18 @@
1010
#include <maths/ImportExport.h>
1111

1212
#include <cstddef>
13+
#include <cstdint>
1314
#include <vector>
1415

15-
#include <stdint.h>
16-
1716
namespace ml {
1817
namespace maths {
1918

20-
//! \brief A collection of utility functions for operations we do
21-
//! integers.
19+
//! \brief A collection of utility functions for operations we do on integers.
2220
//!
2321
//! DESCRIPTION:\n
24-
//! This implements common integer operations: checking alignment,
25-
//! rounding and so on. Also any integer operations we sometimes
26-
//! need that can be done cheaply some "bit twiddling hack".
22+
//! This implements common integer operations: checking alignment, rounding
23+
//! and so on. Also any integer operations we sometimes need that can be done
24+
//! cheaply with some "bit twiddling hack".
2725
class MATHS_EXPORT CIntegerTools {
2826
public:
2927
//! Checks whether a double holds an an integer.
@@ -33,16 +31,17 @@ class MATHS_EXPORT CIntegerTools {
3331
//! <pre class="fragment">
3432
//! \f$p = \left \lceil \log_2(x) \right \rceil\f$
3533
//! </pre>
36-
static std::size_t nextPow2(uint64_t x);
34+
static std::size_t nextPow2(std::uint64_t x);
3735

3836
//! Computes the integer with the reverse of the bits of the binary
3937
//! representation of \p x.
40-
static uint64_t reverseBits(uint64_t x);
38+
static std::uint64_t reverseBits(std::uint64_t x);
4139

4240
//! Check if \p value is \p alignment aligned.
4341
template<typename INT_TYPE>
4442
static inline bool aligned(INT_TYPE value, INT_TYPE alignment) {
45-
return (value % alignment) == static_cast<INT_TYPE>(0);
43+
return alignment == static_cast<INT_TYPE>(0) ||
44+
(value % alignment) == static_cast<INT_TYPE>(0);
4645
}
4746

4847
//! Align \p value to \p alignment rounding up.
@@ -52,7 +51,7 @@ class MATHS_EXPORT CIntegerTools {
5251
//! \note It is assumed that \p value and \p alignment are integral types.
5352
template<typename INT_TYPE>
5453
static inline INT_TYPE ceil(INT_TYPE value, INT_TYPE alignment) {
55-
INT_TYPE result = CIntegerTools::floor(value, alignment);
54+
INT_TYPE result{floor(value, alignment)};
5655
if (result != value) {
5756
result += alignment;
5857
}
@@ -66,7 +65,10 @@ class MATHS_EXPORT CIntegerTools {
6665
//! \note It is assumed that \p value and \p alignment are integral types.
6766
template<typename INT_TYPE>
6867
static inline INT_TYPE floor(INT_TYPE value, INT_TYPE alignment) {
69-
INT_TYPE result = (value / alignment) * alignment;
68+
if (alignment == 0) {
69+
return value;
70+
}
71+
INT_TYPE result{(value / alignment) * alignment};
7072
return result == value ? result : (value < 0 ? result - alignment : result);
7173
}
7274

@@ -78,7 +80,7 @@ class MATHS_EXPORT CIntegerTools {
7880
//! \note It is assumed that \p value and \p alignment are integral types.
7981
template<typename INT_TYPE>
8082
static inline INT_TYPE strictInfimum(INT_TYPE value, INT_TYPE alignment) {
81-
INT_TYPE result = floor(value, alignment);
83+
INT_TYPE result{floor(value, alignment)};
8284

8385
// Since this is a strict lower bound we need to trap the case the
8486
// value is an exact multiple of the alignment.
@@ -121,7 +123,7 @@ class MATHS_EXPORT CIntegerTools {
121123

122124
// Repeatedly apply Euclid's algorithm and use the fact that
123125
// gcd(a, b, c) = gcd(gcd(a, b), c).
124-
INT_TYPE result = gcd(c[0], c[1]);
126+
INT_TYPE result{gcd(c[0], c[1])};
125127
for (std::size_t i = 2; i < c.size(); ++i) {
126128
result = gcd(result, c[i]);
127129
}

lib/maths/CIntegerTools.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ namespace maths {
1616

1717
bool CIntegerTools::isInteger(double value, double tolerance) {
1818
double integerPart;
19-
double remainder = std::modf(value, &integerPart);
19+
double remainder{std::modf(value, &integerPart)};
2020
return remainder <= tolerance * integerPart;
2121
}
2222

23-
std::size_t CIntegerTools::nextPow2(uint64_t x) {
23+
std::size_t CIntegerTools::nextPow2(std::uint64_t x) {
2424
// This is just a binary search for the highest non-zero bit.
2525

26-
static const std::size_t SHIFTS[] = {32u, 16u, 8u, 4u, 2u, 1u};
27-
static const uint64_t MASKS[] = {0xffffffff, 0xffff, 0xff, 0xf, 0x3, 0x1};
26+
static const std::size_t SHIFTS[]{32u, 16u, 8u, 4u, 2u, 1u};
27+
static const std::uint64_t MASKS[]{0xffffffff, 0xffff, 0xff, 0xf, 0x3, 0x1};
2828

29-
std::size_t result = 0u;
29+
std::size_t result{0};
3030
for (std::size_t i = 0; i < 6; ++i) {
31-
uint64_t y = (x >> SHIFTS[i]);
31+
std::uint64_t y = (x >> SHIFTS[i]);
3232
if (y & MASKS[i]) {
3333
result += SHIFTS[i];
3434
x = y;
@@ -37,7 +37,7 @@ std::size_t CIntegerTools::nextPow2(uint64_t x) {
3737
return result + static_cast<std::size_t>(x);
3838
}
3939

40-
uint64_t CIntegerTools::reverseBits(uint64_t x) {
40+
std::uint64_t CIntegerTools::reverseBits(std::uint64_t x) {
4141
// Uses the standard "parallel" approach of swapping adjacent bits, then
4242
// adjacent pairs, quadruples, etc.
4343
x = ((x >> 1) & 0x5555555555555555) | ((x << 1) & 0xaaaaaaaaaaaaaaaa);
@@ -55,7 +55,7 @@ double CIntegerTools::binomial(unsigned int n, unsigned int k) {
5555
return 0.0;
5656
}
5757

58-
double result = 1.0;
58+
double result{1.0};
5959
k = std::min(k, n - k);
6060
for (unsigned int k_ = k; k_ > 0; --k_, --n) {
6161
result *= static_cast<double>(n) / static_cast<double>(k_);

0 commit comments

Comments
 (0)