summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGard Spreemann <gard.spreemann@epfl.ch>2019-10-30 18:11:21 +0100
committerGard Spreemann <gard.spreemann@epfl.ch>2019-10-30 18:11:21 +0100
commit23234f1a360f9f9c930fd5bbd7901fd0ca00871e (patch)
treec545b851f8f026bcb73a87db42b47f186559d84b
parent3e375a78a75c66da5ca40c2c3758a29adb0d0216 (diff)
Endian-safety on big endian architectures.gspr/endian-safety
-rw-r--r--README.md3
-rw-r--r--ripser.cpp33
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]: <http://www.sas.upenn.edu/~vnanda/perseus/>
[GUDHI]: <http://gudhi.gforge.inria.fr>
[sparsehash]: <https://github.com/sparsehash/sparsehash>
-[MIT]: <https://opensource.org/licenses/mit-license.php> \ No newline at end of file
+[MIT]: <https://opensource.org/licenses/mit-license.php>
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 <typename T> T read(std::istream& input_stream) {
+template <typename T> inline void reverse_endianness(T& x) {
+ uint8_t* p = reinterpret_cast<uint8_t *>(&x);
+ std::reverse(p, p + sizeof(T));
+}
+
+template <typename T> T read_le(std::istream& input_stream) {
+ T result;
+ input_stream.read(reinterpret_cast<char*>(&result), sizeof(T));
+ #ifdef BIGENDIAN
+ reverse_endianness(result);
+ #endif
+ return result;
+}
+
+template <typename T> T read_be(std::istream& input_stream) {
T result;
input_stream.read(reinterpret_cast<char*>(&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<int64_t>(input_stream) != 8067171840) {
+ if (read_le<int64_t>(input_stream) != 8067171840) {
std::cerr << "input is not a Dipha file (magic number: 8067171840)" << std::endl;
exit(-1);
}
- if (read<int64_t>(input_stream) != 7) {
+ if (read_le<int64_t>(input_stream) != 7) {
std::cerr << "input is not a Dipha distance matrix (file type: 7)" << std::endl;
exit(-1);
}
- index_t n = read<int64_t>(input_stream);
+ index_t n = read_le<int64_t>(input_stream);
std::vector<value_t> distances;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (i > j)
- distances.push_back(read<double>(input_stream));
+ distances.push_back(read_le<double>(input_stream));
else
- read<double>(input_stream);
+ read_le<double>(input_stream);
return compressed_lower_distance_matrix(std::move(distances));
}
compressed_lower_distance_matrix read_binary(std::istream& input_stream) {
std::vector<value_t> distances;
- while (!input_stream.eof()) distances.push_back(read<value_t>(input_stream));
+ while (!input_stream.eof()) distances.push_back(read_le<value_t>(input_stream));
return compressed_lower_distance_matrix(std::move(distances));
}