Skip to content

Commit 16f3e29

Browse files
authored
Merge pull request #626 from astrorama/feature/solve_nan
Feature/solve nan
2 parents af6610e + 13905a5 commit 16f3e29

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

SEFramework/src/lib/Psf/VariablePsf.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@
2121
* Author: Alejandro Álvarez Ayllón
2222
*/
2323

24-
#include <ElementsKernel/Exception.h>
2524
#include <algorithm>
25+
#include <ElementsKernel/Logging.h>
26+
#include <ElementsKernel/Exception.h>
27+
#include "SEUtils/IsNan.h"
28+
2629
#include "SEFramework/Psf/VariablePsf.h"
2730

31+
static auto stack_logger = Elements::Logging::getLogger("PSFExPsf");
2832

2933
namespace SourceXtractor {
3034

@@ -130,6 +134,16 @@ void VariablePsf::selfTest() {
130134
if (coeff->getWidth() != psf_width || coeff->getHeight() != psf_height) {
131135
throw Elements::Exception() << "Malformed variable PSF, coefficient matrices do not have the same dimensions";
132136
}
137+
for (auto x = 0; x < psf_width; ++x){
138+
for (auto y = 0; y < psf_height; ++y) {
139+
if (fastmath_isnan(coeff->at(x, y))) {
140+
throw Elements::Exception() << "Malformed variable PSF, coefficient matrices contains NANs";
141+
}
142+
else if (fastmath_isinf(coeff->at(x, y))){
143+
throw Elements::Exception() << "Malformed variable PSF, coefficient matrices contains INFs";
144+
}
145+
}
146+
}
133147
}
134148
}
135149

SEImplementation/src/lib/Plugin/Psf/PsfPluginConfig.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,13 @@ static std::shared_ptr<VariablePsf> readPsfEx(std::unique_ptr<CCfits::FITS> &pFi
124124
}
125125

126126
return std::make_shared<VariablePsf>(pixel_sampling, components, group_degrees, coefficients);
127-
} catch (CCfits::FITS::NoSuchHDU&) {
127+
} catch (CCfits::FITS::NoSuchHDU&) { // Make sure we propagate this specific exception
128128
throw;
129129
} catch (CCfits::FitsException &e) {
130130
throw Elements::Exception() << "Error loading PSFEx file: " << e.message();
131+
} catch (...) {
132+
logger.error() << "Failed loading a psf file: " << pFits->name();
133+
throw;
131134
}
132135
}
133136

SEUtils/SEUtils/IsNan.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#ifndef _SEUTILS_ISNAN_H
2+
#define _SEUTILS_ISNAN_H
3+
4+
#include <cstdint>
5+
6+
namespace SourceXtractor {
7+
8+
/*
9+
* From:
10+
* https://github.com/searchivarius/BlogCode/tree/2d947d8c42ab0e10f1f28a2ad036eee10389997a/2017/6/1
11+
*
12+
* IEEE 754 compliant simple functions to test for NANs and INFs.
13+
* This functions are necessary, b/c isnan doesn't work with -Ofast -ffast-math flags
14+
* see http://searchivarius.org/blog/gcc-disables-isnan-and-isinf-when-compiling-ffast-math-flag
15+
*
16+
* See also test files. The file ./regular is compiled without -ffast-math flag and it
17+
* checks for a large number of values that the output of my functions is the same
18+
* as the output of standard functions. For single precision numbers, i.e., for floats
19+
* these checks are exhaustive. That is, I go over the set of all 4B+ possible float values.
20+
* For doubles, this is not possible, so I use tests where the lower 32 bits of mantissa
21+
* are set to zero.
22+
*
23+
* Copyright (c) 2017 Leonid Boytsov
24+
*
25+
* This code is released under the
26+
* Apache License Version 2.0 http://www.apache.org/licenses/.
27+
*
28+
*/
29+
30+
// A mask to extract an exponent from the single-precision floating point number
31+
// 01111111100000000000000000000000
32+
const unsigned FLOAT_EXP_MASK = 0x7F800000;
33+
// A mask to extract a mantissa/fractional part from the single-precision floating point number
34+
// 00000000011111111111111111111111
35+
const unsigned FLOAT_FRAC_PART_MASK = 0x7FFFFF;
36+
37+
inline bool fastmath_isnan(float x) {
38+
union {
39+
uint32_t u;
40+
float f;
41+
} conv;
42+
conv.f = x;
43+
return ((conv.u & FLOAT_EXP_MASK) == FLOAT_EXP_MASK) && ((conv.u & FLOAT_FRAC_PART_MASK) != 0);
44+
};
45+
46+
inline bool fastmath_isinf(float x) {
47+
union {
48+
uint32_t u;
49+
float f;
50+
} conv;
51+
conv.f = x;
52+
return ((conv.u & FLOAT_EXP_MASK) == FLOAT_EXP_MASK) && ((conv.u & FLOAT_FRAC_PART_MASK) == 0);
53+
};
54+
55+
// 0111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
56+
const uint64_t DOUBLE_EXP_MASK = 0x7FF0000000000000ul;
57+
// 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
58+
const uint64_t DOUBLE_FRAC_PART_MASK = 0x000FFFFFFFFFFFFFul;
59+
60+
inline bool fastmath_isnan(double x) {
61+
union {
62+
uint64_t u;
63+
double f;
64+
} conv;
65+
conv.f = x;
66+
return ((conv.u & DOUBLE_EXP_MASK) == DOUBLE_EXP_MASK) && ((conv.u & DOUBLE_FRAC_PART_MASK) != 0);
67+
};
68+
69+
inline bool fastmath_isinf(double x) {
70+
union {
71+
uint64_t u;
72+
double f;
73+
} conv;
74+
conv.f = x;
75+
return ((conv.u & DOUBLE_EXP_MASK) == DOUBLE_EXP_MASK) && ((conv.u & DOUBLE_FRAC_PART_MASK) == 0);
76+
};
77+
78+
} // namespace SourceXtractor
79+
80+
#endif

0 commit comments

Comments
 (0)