Skip to content
Snippets Groups Projects
Commit 7a86be30 authored by Steffen Müthing's avatar Steffen Müthing
Browse files

[vtk] Truncate denormalized floating point values to 0 when writing ASCII

Paraview (well, probably VTK) on macOS crashes when reading ASCII files with
denormalized float values. This seems to be due to libc++'s IO stream
implementation, which sets the fail bit when reading a denormalized value.
On top of that, Paraview just segfaults when encountering a fail bit while
loading VTK files.

libstdc++ does not set the failt bit, and I don't know what is the correct
behavior, but having Paraview mysteriously crash on DUNE output files is not
good.

So this patch truncates subnormal floating point values to 0 when writing ASCII.
This should not seriously influence any visualization results, but it might trip
up people who use exact floating point comparisons for tests (but then you
shouldn't do that anyway...).
parent eaadf1b1
Branches
Tags
1 merge request!350Truncate denormalized floating point values to 0 when writing ASCII
......@@ -9,6 +9,7 @@
#include <string>
#include <iomanip>
#include <cstdint>
#include <cmath>
#include <dune/common/exceptions.hh>
#include <dune/common/indent.hh>
......@@ -137,10 +138,10 @@ namespace Dune
private:
//! write one double data element to output stream
void writeFloat64 (double data) final
{ write_(data); }
{ write_float(data); }
//! write one float data element to output stream
void writeFloat32 (float data) final
{ write_(data); }
{ write_float(data); }
//! write one int data element to output stream
void writeInt32 (std::int32_t data) final
{ write_(data); }
......@@ -164,6 +165,25 @@ namespace Dune
if (counter%numPerLine==0) s << "\n";
}
template<class T>
void write_float(T data)
{
typedef typename PrintType<T>::Type PT;
if(counter%numPerLine==0) s << indent;
else s << " ";
PT out_data = (PT) data;
if (std::fpclassify(out_data) == FP_SUBNORMAL)
{
// truncate denormalized data to 0 to avoid Paraview segfaults on macOS
out_data = 0;
}
const auto original_precision = std::cout.precision();
s << std::setprecision(std::numeric_limits<PT>::digits10) << out_data;
std::cout.precision(original_precision);
counter++;
if (counter%numPerLine==0) s << "\n";
}
std::ostream& s;
int counter;
int numPerLine;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment