From 23234f1a360f9f9c930fd5bbd7901fd0ca00871e Mon Sep 17 00:00:00 2001 From: Gard Spreemann Date: Wed, 30 Oct 2019 18:11:21 +0100 Subject: Endian-safety on big endian architectures. --- README.md | 3 ++- ripser.cpp | 33 +++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2ce826f..ca98030 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Ripser supports several compile-time options. They are switched on by defining t - `INDICATE_PROGRESS`: indicate the current progress in the console - `PRINT_PERSISTENCE_PAIRS`: output the computed persistence pairs (enabled by default in the code; comment out to disable) - `USE_GOOGLE_HASHMAP`: enable support for Google's [sparsehash] data structure; may further reduce memory footprint + - `BIGENDIAN`: build for running on a big endian architecture For example, to build Ripser with support for Google's hashmap: @@ -128,4 +129,4 @@ Ripser is licensed under the [MIT] license (`COPYING.txt`), with an extra clause [Perseus]: [GUDHI]: [sparsehash]: -[MIT]: \ No newline at end of file +[MIT]: diff --git a/ripser.cpp b/ripser.cpp index 1ae62e1..f420f2a 100644 --- a/ripser.cpp +++ b/ripser.cpp @@ -830,10 +830,27 @@ enum file_format { BINARY }; -template T read(std::istream& input_stream) { +template inline void reverse_endianness(T& x) { + uint8_t* p = reinterpret_cast(&x); + std::reverse(p, p + sizeof(T)); +} + +template T read_le(std::istream& input_stream) { + T result; + input_stream.read(reinterpret_cast(&result), sizeof(T)); + #ifdef BIGENDIAN + reverse_endianness(result); + #endif + return result; +} + +template T read_be(std::istream& input_stream) { T result; input_stream.read(reinterpret_cast(&result), sizeof(T)); - return result; // on little endian: boost::endian::little_to_native(result); + #ifndef BIGENDIAN + reverse_endianness(result); + #endif + return result; } compressed_lower_distance_matrix read_point_cloud(std::istream& input_stream) { @@ -929,33 +946,33 @@ compressed_lower_distance_matrix read_distance_matrix(std::istream& input_stream } compressed_lower_distance_matrix read_dipha(std::istream& input_stream) { - if (read(input_stream) != 8067171840) { + if (read_le(input_stream) != 8067171840) { std::cerr << "input is not a Dipha file (magic number: 8067171840)" << std::endl; exit(-1); } - if (read(input_stream) != 7) { + if (read_le(input_stream) != 7) { std::cerr << "input is not a Dipha distance matrix (file type: 7)" << std::endl; exit(-1); } - index_t n = read(input_stream); + index_t n = read_le(input_stream); std::vector distances; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) if (i > j) - distances.push_back(read(input_stream)); + distances.push_back(read_le(input_stream)); else - read(input_stream); + read_le(input_stream); return compressed_lower_distance_matrix(std::move(distances)); } compressed_lower_distance_matrix read_binary(std::istream& input_stream) { std::vector distances; - while (!input_stream.eof()) distances.push_back(read(input_stream)); + while (!input_stream.eof()) distances.push_back(read_le(input_stream)); return compressed_lower_distance_matrix(std::move(distances)); } -- cgit v1.2.3