[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