[Liblas-commits] hg: 2 new changesets
liblas-commits at liblas.org
liblas-commits at liblas.org
Tue Oct 12 12:01:31 EDT 2010
changeset 64d8113f5c63 in /Volumes/Data/www/liblas.org/hg
details: http://hg.liblas.orghg?cmd=changeset;node=64d8113f5c63
summary: Disable copying operations for xml_parser_writer_settings
changeset 5c3ee7cacba8 in /Volumes/Data/www/liblas.org/hg
details: http://hg.liblas.orghg?cmd=changeset;node=5c3ee7cacba8
summary: Incorporated cross-endian binary reade/write utilities based on unrolled loops. Reimplemented intToBits and bitsToInt functions with the new tools. More applications to come. The performance on Windows x64/VisualC++ 10.0 has not decreased but also not increased significantly or at all. The common test of las2las2 TO_core_last_zoom.las gives 0.65s where prior this changeset version gives 0.66-0.68s.
diffstat:
include/liblas/detail/binary.hpp | 254 ++++++++++
include/liblas/detail/private_utility.hpp | 34 +-
include/liblas/external/property_tree/detail/xml_parser_writer_settings.hpp | 6 +
src/CMakeLists.txt | 1 +
src/laspoint.cpp | 20 +-
5 files changed, 285 insertions(+), 30 deletions(-)
diffs (truncated from 390 to 300 lines):
diff -r 77b861e53603 -r 5c3ee7cacba8 include/liblas/detail/binary.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/liblas/detail/binary.hpp Tue Oct 12 17:02:41 2010 +0100
@@ -0,0 +1,254 @@
+// Code taken from Boost.Geometry
+//
+// Copyright Mateusz Loskot <mateusz at loskot.net> 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Load/Store values from/to stream of bytes across different endianness.
+//
+// Original design of unrolled_byte_loops templates based on
+// endian utility library from Boost C++ Libraries,
+// source: boost/spirit/home/support/detail/integer/endian.hpp
+// Copyright Darin Adler 2000
+// Copyright Beman Dawes 2006, 2009
+// Distributed under the Boost Software License, Version 1.0.
+
+#ifndef LIBLAS_DETAIL_BINARY_HPP_INCLUDED
+#define LIBLAS_DETAIL_BINARY_HPP_INCLUDED
+
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <cstddef>
+
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/detail/endian.hpp>
+#include <boost/type_traits/is_signed.hpp>
+
+#if CHAR_BIT != 8
+#error Platforms with CHAR_BIT != 8 are not supported
+#endif
+
+// TODO: mloskot - add static asserts to validate compile-time pre-conditions
+
+namespace liblas {
+
+namespace detail { namespace binary {
+
+// Endianness tag used to indicate load/store directoin
+
+struct big_endian_tag {};
+struct little_endian_tag {};
+
+#ifdef BOOST_BIG_ENDIAN
+typedef big_endian_tag native_endian_tag;
+#else
+typedef little_endian_tag native_endian_tag;
+#endif
+
+// Unrolled loops for loading and storing streams of bytes.
+
+template <typename T, std::size_t N, bool Sign = boost::is_signed<T>::value>
+struct unrolled_byte_loops
+{
+ typedef unrolled_byte_loops<T, N - 1, Sign> next;
+
+ template <typename Iterator>
+ static T load_forward(Iterator& bytes)
+ {
+ T const value = *bytes;
+ ++bytes;
+ return value | (next::load_forward(bytes) << 8);
+ }
+
+ template <typename Iterator>
+ static T load_backward(Iterator& bytes)
+ {
+ T const value = *(bytes - 1);
+ --bytes;
+ return value | (next::load_backward(bytes) << 8);
+ }
+
+ template <typename Iterator>
+ static void store_forward(Iterator& bytes, T value)
+ {
+ *bytes = static_cast<char>(value);
+ next::store_forward(++bytes, value >> 8);
+ }
+
+ template <typename Iterator>
+ static void store_backward(Iterator& bytes, T value)
+ {
+ *(bytes - 1) = static_cast<char>(value);
+ next::store_backward(--bytes, value >> 8);
+ }
+};
+
+template <typename T>
+struct unrolled_byte_loops<T, 1, false>
+{
+ template <typename Iterator>
+ static T load_forward(Iterator& bytes)
+ {
+ return *bytes;
+ }
+
+ template <typename Iterator>
+ static T load_backward(Iterator& bytes)
+ {
+ return *(bytes - 1);
+ }
+
+ template <typename Iterator>
+ static void store_forward(Iterator& bytes, T value)
+ {
+ // typename Iterator::value_type
+ *bytes = static_cast<char>(value);
+ }
+
+ template <typename Iterator>
+ static void store_backward(Iterator& bytes, T value)
+ {
+ *(bytes - 1) = static_cast<char>(value);
+ }
+};
+
+template <typename T>
+struct unrolled_byte_loops<T, 1, true>
+{
+ template <typename Iterator>
+ static T load_forward(Iterator& bytes)
+ {
+ return *reinterpret_cast<const signed char*>(&*bytes);
+ }
+
+ template <typename Iterator>
+ static T load_backward(Iterator& bytes)
+ {
+ return *reinterpret_cast<const signed char*>(&*(bytes - 1));
+ }
+
+ template <typename Iterator>
+ static void store_forward(Iterator& bytes, T value)
+ {
+ *bytes = static_cast<char>(value);
+ }
+
+ template <typename Iterator>
+ static void store_backward(Iterator& bytes, T value)
+ {
+ *(bytes - 1) = static_cast<char>(value);
+ }
+};
+
+// load/store operation dispatch
+// E, E - source and target endianness is the same
+// E1, E2 - source and target endianness is different (big-endian <-> little-endian)
+
+template <typename T, std::size_t N, typename Iterator, typename E>
+T load_dispatch(Iterator& bytes, E, E)
+{
+ return unrolled_byte_loops<T, N>::load_forward(bytes);
+}
+
+template <typename T, std::size_t N, typename Iterator, typename E1, typename E2>
+T load_dispatch(Iterator& bytes, E1, E2)
+{
+ std::advance(bytes, N);
+ return unrolled_byte_loops<T, N>::load_backward(bytes);
+}
+
+template <typename T, std::size_t N, typename Iterator, typename E>
+void store_dispatch(Iterator& bytes, T value, E, E)
+{
+ return unrolled_byte_loops<T, N>::store_forward(bytes, value);
+}
+
+template <typename T, std::size_t N, typename Iterator, typename E1, typename E2>
+void store_dispatch(Iterator& bytes, T value, E1, E2)
+{
+ std::advance(bytes, N);
+ return unrolled_byte_loops<T, N>::store_backward(bytes, value);
+}
+
+// numeric value holder for load/store operation
+
+template <typename T>
+struct endian_value_base
+{
+ typedef T value_type;
+ typedef native_endian_tag endian_type;
+
+ endian_value_base() : value(T()) {}
+ explicit endian_value_base(T value) : value(value) {}
+
+ operator T() const
+ {
+ return value;
+ }
+
+protected:
+ T value;
+};
+
+template <typename T, std::size_t N = sizeof(T)>
+struct endian_value : public endian_value_base<T>
+{
+ typedef endian_value_base<T> base;
+
+ endian_value() {}
+ explicit endian_value(T value) : base(value) {}
+
+ template <typename E, typename Iterator>
+ void load(Iterator bytes)
+ {
+ base::value = load_dispatch<T, N>(bytes, typename base::endian_type(), E());
+ }
+
+ template <typename E, typename Iterator>
+ void store(Iterator bytes)
+ {
+ store_dispatch<T, N>(bytes, base::value, typename base::endian_type(), E());
+ }
+};
+
+template <>
+struct endian_value<double, 8> : public endian_value_base<double>
+{
+ typedef endian_value_base<double> base;
+
+ endian_value() {}
+ explicit endian_value(double value) : base(value) {}
+
+ template <typename E, typename Iterator>
+ void load(Iterator bytes)
+ {
+ endian_value<boost::uint64_t, 8> raw;
+ raw.load<E>(bytes);
+
+ double& target_value = base::value;
+ std::memcpy(&target_value, &raw, sizeof(double));
+ }
+
+ template <typename E, typename Iterator>
+ void store(Iterator bytes)
+ {
+ boost::uint64_t raw;
+ double const& source_value = base::value;
+ std::memcpy(&raw, &source_value, sizeof(boost::uint64_t));
+
+ store_dispatch
+ <
+ boost::uint64_t,
+ sizeof(boost::uint64_t)
+ >(bytes, raw, typename base::endian_type(), E());
+ }
+};
+
+}} // namespace detail::binary
+} // namespace liblas
+
+#endif // LIBLAS_DETAIL_BINARY_HPP_INCLUDED
diff -r 77b861e53603 -r 5c3ee7cacba8 include/liblas/detail/private_utility.hpp
--- a/include/liblas/detail/private_utility.hpp Tue Oct 12 09:10:28 2010 -0500
+++ b/include/liblas/detail/private_utility.hpp Tue Oct 12 17:02:41 2010 +0100
@@ -44,6 +44,7 @@
#include <liblas/detail/pointrecord.hpp>
#include <liblas/detail/endian.hpp>
+#include <liblas/detail/binary.hpp>
// boost
#include <boost/concept_check.hpp>
#include <boost/cstdint.hpp>
@@ -371,32 +372,23 @@
// adapted from http://www.cplusplus.com/forum/beginner/3076/
template <typename IntegerType>
-inline IntegerType bitsToInt( IntegerType& result,
- std::vector<boost::uint8_t> const& data,
- std::size_t index)
+inline IntegerType bitsToInt(IntegerType& output,
+ std::vector<boost::uint8_t> const& data,
+ std::size_t index)
{
- result = 0;
-
-#if defined(LIBLAS_BIG_ENDIAN)
- for (boost::uint32_t n = 0; n < sizeof( result ); n++)
-#else
- for (boost::int32_t n = sizeof( result )-1; n >= 0; n--)
-#endif
- result = (result << 8) +data[ n + index ];
- return result;
+ binary::endian_value<IntegerType> value;
+ value.template load<binary::little_endian_tag>(data.begin() + index);
+ output = value;
+ return output;
}
template <typename IntegerType>
-inline void intToBits( IntegerType value,
- std::vector<boost::uint8_t> & data,
- std::size_t index )
+inline void intToBits(IntegerType input,
More information about the Liblas-commits
mailing list