From f618c5a1f664e72994c37b6e1d4232a1673206aa Mon Sep 17 00:00:00 2001 From: Yury Melnichek Date: Sat, 29 Jan 2011 19:08:15 +0100 Subject: [PATCH] Move ZigZagEncode() and ZigZagDecode() to bits. Factor out BitwiseMerge() and BitwiseSplit(). --- base/bits.hpp | 28 ++++++++++++++++++++++++++++ coding/varint.hpp | 22 +++++----------------- geometry/pointu_to_uint64.hpp | 10 ++++------ 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/base/bits.hpp b/base/bits.hpp index 5a7127476d..932128d53f 100644 --- a/base/bits.hpp +++ b/base/bits.hpp @@ -1,5 +1,6 @@ #pragma once #include "base.hpp" +#include "../std/type_traits.hpp" namespace bits { @@ -73,6 +74,18 @@ namespace bits return (x << 1) | (x >> (sizeof(T) * 8 - 1)); } + template inline typename make_unsigned::type ZigZagEncode(T x) + { + STATIC_ASSERT(is_signed::value); + return (x << 1) ^ (x >> (sizeof(x) * 8 - 1)); + } + + template inline typename make_signed::type ZigZagDecode(T x) + { + STATIC_ASSERT(is_unsigned::value); + return (x >> 1) ^ -static_cast::type>(x & 1); + } + inline uint32_t PerfectShuffle(uint32_t x) { x = ((x & 0x0000FF00) << 8) | ((x >> 8) & 0x0000FF00) | (x & 0xFF0000FF); @@ -90,4 +103,19 @@ namespace bits x = ((x & 0x0000FF00) << 8) | ((x >> 8) & 0x0000FF00) | (x & 0xFF0000FF); return x; } + + inline uint64_t BitwiseMerge(uint32_t x, uint32_t y) + { + uint32_t const hi = PerfectShuffle((y & 0xFFFF0000) | (x >> 16)); + uint32_t const lo = PerfectShuffle(((y & 0xFFFF) << 16 ) | (x & 0xFFFF)); + return (static_cast(hi) << 32) + lo; + } + + inline void BitwiseSplit(uint64_t v, uint32_t & x, uint32_t & y) + { + uint32_t const hi = bits::PerfectUnshuffle(static_cast(v >> 32)); + uint32_t const lo = bits::PerfectUnshuffle(static_cast(v & 0xFFFFFFFFULL)); + x = ((hi & 0xFFFF) << 16) | (lo & 0xFFFF); + y = (hi & 0xFFFF0000) | (lo >> 16); + } } diff --git a/coding/varint.hpp b/coding/varint.hpp index 64b2191290..9f27bc591a 100644 --- a/coding/varint.hpp +++ b/coding/varint.hpp @@ -1,8 +1,8 @@ #pragma once #include "write_to_sink.hpp" - #include "../base/assert.hpp" #include "../base/base.hpp" +#include "../base/bits.hpp" #include "../base/exception.hpp" #include "../base/stl_add.hpp" #include "../std/type_traits.hpp" @@ -163,28 +163,16 @@ template T ReadVarUint(TSource & src) */ } -template inline typename make_unsigned::type ZigZagEncode(T x) -{ - STATIC_ASSERT(is_signed::value); - return (x << 1) ^ (x >> (sizeof(x) * 8 - 1)); -} - -template inline typename make_signed::type ZigZagDecode(T x) -{ - STATIC_ASSERT(is_unsigned::value); - return (x >> 1) ^ -static_cast::type>(x & 1); -} - template void WriteVarInt(TSink & dst, T value) { STATIC_ASSERT(is_signed::value); - WriteVarUint(dst, ZigZagEncode(value)); + WriteVarUint(dst, bits::ZigZagEncode(value)); } template T ReadVarInt(TSource & src) { STATIC_ASSERT(is_signed::value); - return ZigZagDecode(ReadVarUint::type>(src)); + return bits::ZigZagDecode(ReadVarUint::type>(src)); } DECLARE_EXCEPTION(ReadVarIntException, RootException); @@ -260,7 +248,7 @@ template inline void const * ReadVarInt64Array(void const * pBeg, void const * pEnd, F f) { return impl::ReadVarInt64Array( - pBeg, impl::ReadVarInt64ArrayUntilBufferEnd(pEnd), f, &ZigZagDecode); + pBeg, impl::ReadVarInt64ArrayUntilBufferEnd(pEnd), f, &bits::ZigZagDecode); } template inline @@ -273,7 +261,7 @@ template inline void const * ReadVarInt64Array(void const * pBeg, size_t count, F f) { return impl::ReadVarInt64Array( - pBeg, impl::ReadVarInt64ArrayGivenSize(count), f, &ZigZagDecode); + pBeg, impl::ReadVarInt64ArrayGivenSize(count), f, &bits::ZigZagDecode); } template inline diff --git a/geometry/pointu_to_uint64.hpp b/geometry/pointu_to_uint64.hpp index c114ae898a..9c074cde0e 100644 --- a/geometry/pointu_to_uint64.hpp +++ b/geometry/pointu_to_uint64.hpp @@ -9,16 +9,14 @@ namespace m2 inline PointU Uint64ToPointU(int64_t v) { - uint32_t const hi = bits::PerfectUnshuffle(static_cast(v >> 32)); - uint32_t const lo = bits::PerfectUnshuffle(static_cast(v & 0xFFFFFFFFULL)); - return PointU((((hi & 0xFFFF) << 16) | (lo & 0xFFFF)), ((hi & 0xFFFF0000) | (lo >> 16))); + PointU res; + bits::BitwiseSplit(v, res.x, res.y); + return res; } inline uint64_t PointUToUint64(PointU const & pt) { - uint64_t const res = - (static_cast(bits::PerfectShuffle((pt.y & 0xFFFF0000) | (pt.x >> 16))) << 32) | - bits::PerfectShuffle(((pt.y & 0xFFFF) << 16 ) | (pt.x & 0xFFFF)); + uint64_t const res = bits::BitwiseMerge(pt.x, pt.y); ASSERT_EQUAL(pt, Uint64ToPointU(res), ()); return res; }