固定次元グリッドの範囲判定と一次元化
lib/graph/grid.hpp
インクルード
#include "graph/grid.hpp"
クラス
| 名前 | 説明 |
|---|---|
Grid |
固定次元グリッドの範囲判定と一次元化 |
検証
検証プログラム(1)
-
test/aoj/jag/doubling.test.cpp
test/aoj/jag/doubling.test.cpp
実装
#pragma once
#include <cstdint>
#include <utility>
namespace internal {
template <int Index>
struct grid_impl {
template <class Head, class... Tail>
constexpr grid_impl(Head &&head, Tail &&...tail) : limit(head), impl(std::forward<Tail>(tail)...) {}
template <class Head, class... Tail>
constexpr bool in_field(Head x, Tail &&...tail) const {
return 0 <= x && x < limit && impl.in_field(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
constexpr std::int64_t flatten(Head x, Tail &&...tail) const {
return x + limit * impl.flatten(std::forward<Tail>(tail)...);
}
private:
std::int64_t limit;
grid_impl<Index - 1> impl;
};
template <>
struct grid_impl<0> {
constexpr grid_impl() {}
constexpr bool in_field() const { return true; }
constexpr std::int64_t flatten() const { return 0; }
};
} // namespace internal
/// @brief 固定次元グリッドの範囲判定と一次元化
/// @tparam Index 次元数
/// @complexity 構築・`in_field`・`flatten` は $O(Index)$
template <int Index>
struct Grid {
/// @brief 各次元の大きさからグリッドを構築する
/// @complexity $O(Index)$
template <class... Args>
constexpr Grid(Args &&...args) : entity(std::forward<Args>(args)...) {
static_assert(sizeof...(Args) == Index);
}
/// @brief 座標が全次元の範囲内か返す
/// @complexity $O(Index)$
template <class... Args>
constexpr bool in_field(Args &&...args) const {
static_assert(sizeof...(Args) == Index);
return entity.in_field(std::forward<Args>(args)...);
}
/// @brief 座標を行優先の一次元indexへ変換する
/// @complexity $O(Index)$
template <class... Args>
constexpr std::int64_t flatten(Args &&...args) const {
static_assert(sizeof...(Args) == Index);
return entity.flatten(std::forward<Args>(args)...);
}
private:
internal::grid_impl<Index> entity;
};
bundled
#line 2 "lib/graph/grid.hpp"
#include <cstdint>
#include <utility>
namespace internal {
template <int Index>
struct grid_impl {
template <class Head, class... Tail>
constexpr grid_impl(Head &&head, Tail &&...tail) : limit(head), impl(std::forward<Tail>(tail)...) {}
template <class Head, class... Tail>
constexpr bool in_field(Head x, Tail &&...tail) const {
return 0 <= x && x < limit && impl.in_field(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
constexpr std::int64_t flatten(Head x, Tail &&...tail) const {
return x + limit * impl.flatten(std::forward<Tail>(tail)...);
}
private:
std::int64_t limit;
grid_impl<Index - 1> impl;
};
template <>
struct grid_impl<0> {
constexpr grid_impl() {}
constexpr bool in_field() const { return true; }
constexpr std::int64_t flatten() const { return 0; }
};
} // namespace internal
/// @brief 固定次元グリッドの範囲判定と一次元化
/// @tparam Index 次元数
/// @complexity 構築・`in_field`・`flatten` は $O(Index)$
template <int Index>
struct Grid {
/// @brief 各次元の大きさからグリッドを構築する
/// @complexity $O(Index)$
template <class... Args>
constexpr Grid(Args &&...args) : entity(std::forward<Args>(args)...) {
static_assert(sizeof...(Args) == Index);
}
/// @brief 座標が全次元の範囲内か返す
/// @complexity $O(Index)$
template <class... Args>
constexpr bool in_field(Args &&...args) const {
static_assert(sizeof...(Args) == Index);
return entity.in_field(std::forward<Args>(args)...);
}
/// @brief 座標を行優先の一次元indexへ変換する
/// @complexity $O(Index)$
template <class... Args>
constexpr std::int64_t flatten(Args &&...args) const {
static_assert(sizeof...(Args) == Index);
return entity.flatten(std::forward<Args>(args)...);
}
private:
internal::grid_impl<Index> entity;
};