From 0013efd3cc0c2aa9150c983babd52d3de8e32744 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 19 Aug 2018 17:09:03 +0200 Subject: Clean up implementation header and inline code used only there --- chilbert/Hilbert.ipp | 254 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 93 deletions(-) (limited to 'chilbert/Hilbert.ipp') diff --git a/chilbert/Hilbert.ipp b/chilbert/Hilbert.ipp index 44b5b5f..81eb7fd 100644 --- a/chilbert/Hilbert.ipp +++ b/chilbert/Hilbert.ipp @@ -21,26 +21,24 @@ #include "chilbert/BigBitVec.hpp" #include "chilbert/FixBitVec.hpp" -#include "chilbert/GetBits.hpp" -#include "chilbert/GetLocation.hpp" #include "chilbert/GrayCodeRank.hpp" #include "chilbert/Hilbert.hpp" -#include "chilbert/SetBits.hpp" -#include "chilbert/SetLocation.hpp" #include "chilbert/StaticBitVec.hpp" #include #include +#include #include -// The dimension across which the Hilbert curve travels -// principally. -// D0 is d + 1, where d is the actual dimension you want to -// walk across. -// MUST HAVE 0 <= D0 < n -#define D0 1 - namespace chilbert { +namespace detail { + +/** The dimension across which the Hilbert curve travels principally. + * + * D0 is d + 1, where d is the actual dimension you want to walk across. + * MUST HAVE 0 <= D0 < n. + */ +static constexpr size_t D0 = 1; template size_t @@ -65,6 +63,70 @@ num_bits(const StaticBitVec&, void* = nullptr) return N; } +/** Copy a range of bits from one field to the start of another. + * + * @param h Source bit field + * @param n Number of bits + * @param i Start bit index in source + * @param[out] w Destination bit field + */ +template +inline void +get_bits(const H& h, const size_t n, const size_t i, I& w) +{ + for (size_t j = 0; j < n; j++) { + set_bit(w, j, test_bit(h, i + j)); + } +} + +/** Set a range of bits in one field from the start of another. + * + * @param[out] h Destination bit field + * @param n Number of bits + * @param i Start bit index in destination + * @param w Source bit field + */ +template +inline void +set_bits(H& h, const size_t n, const size_t i, const I& w) +{ + for (size_t j = 0; j < n; j++) { + set_bit(h, i + j, test_bit(w, j)); + } +} + +/** Set the leading bits in `l` to bit `i` from the corresponding value in `p`. + * + * @param p Point. + * @param n Number of bits to set. + * @param i Bit position to copy from values in `p`. + * @param[out] l Output bits. + */ +template +inline void +get_location(const P* const p, const size_t n, const size_t i, I& l) +{ + for (size_t j = 0; j < n; ++j) { + set_bit(l, j, test_bit(p[j], i)); + } +} + +/** Set bit `i` in values in `p` to the corresponding leadings bits in `l`. + * + * @param[out] p Point. + * @param n Number of bits to set. + * @param i Bit position to set in values in `p`. + * @param l Input bits. + */ +template +inline void +set_location(P* const p, const size_t n, const size_t i, const I& l) +{ + for (size_t j = 0; j < n; j++) { + set_bit(p[j], i, test_bit(l, j)); + } +} + // 'Transforms' a point. template inline void @@ -131,13 +193,12 @@ update2(const I& l, const I& t, const size_t n, I& e, size_t& d) template inline void -_coords_to_index(const P* const p, - const size_t m, - const size_t n, - H& h, - I&& scratch, - size_t* const ds = nullptr // #HACK -) +coords_to_index(const P* const p, + const size_t m, + const size_t n, + H& h, + I&& scratch, + size_t* const ds = nullptr) { I e{std::move(scratch)}; I l{e}; @@ -153,7 +214,6 @@ _coords_to_index(const P* const p, size_t d = D0; size_t ho = m * n; for (intptr_t i = static_cast(m - 1); i >= 0; i--) { - // #HACK if (ds) { ds[i] = d; } @@ -182,25 +242,9 @@ _coords_to_index(const P* const p, gray_code_inv(h); } -template -inline void -coords_to_index(const P* const p, const size_t m, const size_t n, H& h) -{ - assert(num_bits(h) >= n * m); - assert(num_bits(p[0]) >= m); - - if (n <= FBV_BITS) { - // Intermediate variables will fit in fixed width - _coords_to_index(p, m, n, h, CFixBitVec(n)); - } else { - // Otherwise, they must be BigBitVecs - _coords_to_index(p, m, n, h, CBigBitVec(n)); - } -} - template inline void -_index_to_coords(P* p, const size_t m, const size_t n, const H& h, I&& scratch) +index_to_coords(P* p, const size_t m, const size_t n, const H& h, I&& scratch) { I e{std::move(scratch)}; I l{e}; @@ -240,33 +284,15 @@ _index_to_coords(P* p, const size_t m, const size_t n, const H& h, I&& scratch) } } -template -inline void -index_to_coords(P* const p, const size_t m, const size_t n, const H& h) -{ - assert(m > 0); - assert(n > 0); - assert(num_bits(h) >= n * m); - assert(num_bits(p[0]) >= m); - - if (n <= FBV_BITS) { - // Intermediate variables will fit in fixed width - _index_to_coords(p, m, n, h, CFixBitVec(n)); - } else { - // Otherwise, they must be BigBitVecs - _index_to_coords(p, m, n, h, CBigBitVec(n)); - } -} - template inline void -_coords_to_compact_index(const P* const p, - const size_t* const ms, - const size_t n, - HC& hc, - I&& scratch, - size_t M = 0, - size_t m = 0) +coords_to_compact_index(const P* const p, + const size_t* const ms, + const size_t n, + HC& hc, + I&& scratch, + size_t M = 0, + size_t m = 0) { // Get total precision and max precision if not supplied if (M == 0 || m == 0) { @@ -291,46 +317,28 @@ _coords_to_compact_index(const P* const p, if (mn > FBV_BITS) { CBigBitVec h(mn); - _coords_to_index(p, m, n, h, std::move(scratch), ds); + detail::coords_to_index( + p, m, n, h, std::move(scratch), ds); compact_index(ms, ds, n, m, h, hc); } else { CFixBitVec h(mn); - _coords_to_index(p, m, n, h, std::move(scratch), ds); + detail::coords_to_index( + p, m, n, h, std::move(scratch), ds); compact_index(ms, ds, n, m, h, hc); } delete[] ds; } -template -inline void -coords_to_compact_index(const P* const p, - const size_t* const ms, - size_t n, - HC& hc, - const size_t M, - const size_t m) -{ - if (n <= FBV_BITS) { - // Intermediate variables will fit in fixed width - _coords_to_compact_index( - p, ms, n, hc, CFixBitVec(n), M, m); - } else { - // Otherwise, they must be BigBitVecs - _coords_to_compact_index( - p, ms, n, hc, CBigBitVec(n), M, m); - } -} - template inline void -_compact_index_to_coords(P* const p, - const size_t* ms, - const size_t n, - const HC& hc, - I&& scratch, - size_t M, - size_t m) +compact_index_to_coords(P* const p, + const size_t* ms, + const size_t n, + const HC& hc, + I&& scratch, + size_t M, + size_t m) { I e{std::move(scratch)}; I l{e}; @@ -359,7 +367,7 @@ _compact_index_to_coords(P* const p, e.reset(); l.reset(); for (size_t j = 0; j < n; j++) { - p[j] = 0; + reset_bits(p[j]); } // Work from MSB to LSB @@ -396,6 +404,64 @@ _compact_index_to_coords(P* const p, } } +} // namespace detail + +template +inline void +coords_to_index(const P* const p, const size_t m, const size_t n, H& h) +{ + assert(detail::num_bits(h) >= n * m); + assert(detail::num_bits(p[0]) >= m); + + if (n <= FBV_BITS) { + // Intermediate variables will fit in fixed width + detail::coords_to_index(p, m, n, h, CFixBitVec(n)); + } else { + // Otherwise, they must be BigBitVecs + detail::coords_to_index(p, m, n, h, CBigBitVec(n)); + } +} + +template +inline void +index_to_coords(P* const p, const size_t m, const size_t n, const H& h) +{ + assert(m > 0); + assert(n > 0); + assert(detail::num_bits(h) >= n * m); + assert(detail::num_bits(p[0]) >= m); + + if (n <= FBV_BITS) { + // Intermediate variables will fit in fixed width + detail::index_to_coords(p, m, n, h, CFixBitVec(n)); + } else { + // Otherwise, they must be BigBitVecs + detail::index_to_coords(p, m, n, h, CBigBitVec(n)); + } +} + +template +inline void +coords_to_compact_index(const P* const p, + const size_t* const ms, + size_t n, + HC& hc, + const size_t M, + const size_t m) +{ + assert(hc.size() >= std::accumulate(ms, ms + n, size_t(0))); + + if (n <= FBV_BITS) { + // Intermediate variables will fit in fixed width + detail::coords_to_compact_index( + p, ms, n, hc, CFixBitVec(n), M, m); + } else { + // Otherwise, they must be BigBitVecs + detail::coords_to_compact_index( + p, ms, n, hc, CBigBitVec(n), M, m); + } +} + template inline void compact_index_to_coords(P* const p, @@ -405,15 +471,17 @@ compact_index_to_coords(P* const p, const size_t M, const size_t m) { + assert(hc.size() >= std::accumulate(ms, ms + n, size_t(0))); + if (n <= FBV_BITS) { // Intermediate variables will fit in fixed width CFixBitVec scratch(n); - _compact_index_to_coords( + detail::compact_index_to_coords( p, ms, n, hc, std::move(scratch), M, m); } else { // Otherwise, they must be BigBitVecs CBigBitVec scratch(n); - _compact_index_to_coords( + detail::compact_index_to_coords( p, ms, n, hc, std::move(scratch), M, m); } } -- cgit v1.2.1