Mentions légales du service

Skip to content
Snippets Groups Projects
Commit c853d5e1 authored by Quentin Khan's avatar Quentin Khan
Browse files

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
No related branches found
No related tags found
No related merge requests found
#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();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment