Commit c853d5e1 authored by Quentin Khan's avatar Quentin Khan

Add ZCurve indexer for adaptive algorithm

This class provides conversion from position to zcurve index. The position
may be relative to a center point or given as a boolean value tuple.
parent 20f8d01f
#ifndef SCALFMM_SPACE_CURVE_HPP_
#define SCALFMM_SPACE_CURVE_HPP_
#include "Utils/FPoint.hpp"
/** Provides the corner traversal order of an N dimension hypercube
*
* The positions returned are array of booleans. Each boolean tells where
* to place the element in the binary grid.
*
* For instance, in 2D:
*
*
* __0__ __1__
* | | |
* 0| | X | pos(X) = [true, false]
* |_____|_____|
* | | |
* 1| | Y | pos(Y) = [true, true ]
* |_____|_____|
*
*
* \tparam Dim The hypercube dimension.
*/
template<std::size_t _Dim>
class FZCurve {
public:
/// Space dimension count
constexpr static const std::size_t Dim = _Dim;
/// Position type used
using position_t = FPoint<bool, Dim>;
/// Position count in the grid
constexpr static std::size_t pos_count = Fpow(2,Dim);
private:
/// Array of positions type
using position_array_t = std::array<position_t, pos_count>;
/// Array to cache the positions corresponding to indexes
static const position_array_t _positions;
/** Creates an array of positions to initialize #_positions */
static position_array_t create_array() noexcept {
position_array_t positions;
for(std::size_t i = 0; i < pos_count; ++i) {
for(std::size_t j = Dim-1, k = i; k != 0; --j, k >>=1) {
positions[i][j] = k % 2;
}
}
return positions;
}
public:
/** The position corresponding to an index
*
* \param idx The index of the point in the space filling curve
* \return The position corresponding to the space filling curve index
*/
static position_t position(std::size_t idx) noexcept {
return _positions[idx];
}
/** Index in the space filling curve of a boolean position
*
* \param p The position
* \return The space filling curve index corresponding to the position
*/
static std::size_t index(const position_t& p) noexcept {
std::size_t idx = 0;
for(auto i : p) {
idx <<= 1;
idx += i;
}
return idx;
}
/** Index in the space filling curve of a real position relative to the center of the hypercube
*
* \param p The position
* \param center The center of the hypercube
* \return The space filling curve index corresponding to the position
*/
template<typename Real>
static std::size_t index(const FPoint<Real, Dim>& p, const FPoint<Real, Dim>& center) noexcept {
std::size_t idx = 0;
for(std::size_t i = 0; i < Dim; ++i) {
idx <<= 1;
idx += p[i] > center[i];
}
return idx;
}
};
// Initialization of static variable
template<std::size_t _Dim>
const typename FZCurve<_Dim>::position_array_t FZCurve<_Dim>::_positions(FZCurve<_Dim>::create_array());
#endif
#include <cassert>
#include <iostream>
#include "test_Abstract.hpp"
#include "Utils/FConstFuncs.hpp"
#include "Adaptive/new/FZCurve.hpp"
namespace scalfmm {
namespace tests {
struct test_ZCurve : public test_Abstract<test_ZCurve> {
using Real = double;
constexpr static const std::size_t Dim = 3;
constexpr static const std::size_t pos_count = FZCurve<Dim>::pos_count;
using boolpos_t = FZCurve<Dim>::position_t;
using position_t = FPoint<Real, Dim>;
void run_all() {
RUN(test_curve_1);
RUN(test_curve_2);
}
// Tests that the position and index functions are the inverse of each other
void test_curve_1 () {
FZCurve<Dim> indexer;
std::array<boolpos_t, pos_count> pos;
//std::cout << std::endl;
for(std::size_t i = 0; i < pos_count; ++i) {
pos[i] = indexer.position(i);
std::size_t j = indexer.index(pos[i]);
//std::cout << i << pos[i] << j << std::endl;
assert(i == j);
}
}
// Tests that the position and index 2 overload functions are the inverse of each other
void test_curve_2 () {
FZCurve<Dim> indexer;
position_t center = {50,50,50};
std::array<position_t, pos_count> pos;
for(std::size_t i = 0; i < pos_count; ++i) {
pos[i] = position_t(indexer.position(i)) * 75;
std::size_t j = indexer.index(pos[i], center);
assert(i == j);
}
}
};
}
}
int main() {
scalfmm::tests::test_ZCurve().run_all();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment