Skip to content

Commit

Permalink
refactor blade_type_from(_dimension) traits
Browse files Browse the repository at this point in the history
Define trait `blade_type_from_dimension`, which determines the `blade`
type given the algebra type and a random access range as a non-type template
parameter. The random access range specifies the dimensions of the
`blade`.

Update the `blade_type_from` trait to take an algebra type and a
non-type template parameter that is either a mask or a range of
dimensions. A range of `bool` is interpreted as a mask. A range of
`std::size_t` is interpreted as dimensions.

Change-Id: I08d04592475f294e755e5fef88d1dfd7cbfdaea6
  • Loading branch information
oliverlee committed Sep 29, 2024
1 parent 9df6938 commit 663d8c7
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 30 deletions.
73 changes: 58 additions & 15 deletions rigid_geometric_algebra/blade_type_from.hpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,78 @@
#pragma once

#include "rigid_geometric_algebra/algebra_type.hpp"
#include "rigid_geometric_algebra/blade.hpp"
#include "rigid_geometric_algebra/blade_ordering.hpp"
#include "rigid_geometric_algebra/detail/indices_array.hpp"
#include "rigid_geometric_algebra/is_algebra.hpp"

#include <cstddef>
#include <ranges>
#include <utility>

namespace rigid_geometric_algebra {

/// determine the blade type from a `blade_ordering` value
/// determine the blade type from a range of dimensions
/// @tparam A algebra type
/// @tparam dimensions random access range of dimensions
///
/// ~~~{.cpp}
/// static_assert(std::is_same_v<
/// blade<A, 0, 2, 1>,
/// blade_type_from_dimensions_t<A, std::array{0, 2, 1}>
/// >);
/// ~~~
///
/// @{

template <class A, std::ranges::random_access_range auto dimensions>
requires is_algebra_v<A>
struct blade_type_from_dimensions
{
using type =
decltype([]<std::size_t... Is>(
std::index_sequence<Is...>) -> blade<A, dimensions[Is]...> {
return {};
}(std::make_index_sequence<dimensions.size()>{}));
};

template <class A, auto dimensions>
using blade_type_from_dimensions_t =
typename blade_type_from_dimensions<A, dimensions>::type;

/// @}

/// determine the blade type from a dimension mask or range of dimensions
/// @tparam A algebra type
/// @tparam mask_or_dimensions forward range of `bool` or random access range
/// of dimensions
///
/// Determins the `blade` type given an algebra type and either a mask or
/// dimensions. If `mask_or_dimensions` has a range value type of `bool`, it is
/// interpreted as a mask. Otherwise, it is interpreted as dimensions.
///
/// @note The `blade` type given a mask is always in canonical form.
///
/// @{

template <blade_ordering ord>
template <class A, std::ranges::forward_range auto mask_or_dimensions>
requires is_algebra_v<A>
struct blade_type_from
{
template <std::size_t... Is>
static constexpr auto impl(std::index_sequence<Is...>)
{
return blade<
algebra_type_t<decltype(ord)>,
std::get<Is>(detail::indices_array<ord.mask>)...>{};
}

using type = decltype(impl(std::make_index_sequence<ord.mask.count()>{}));
using type = typename decltype([] {
if constexpr (
std::is_same_v<
bool,
std::ranges::range_value_t<decltype(mask_or_dimensions)>>) {
static constexpr auto dimensions =
detail::indices_array<mask_or_dimensions>;
return blade_type_from_dimensions<A, dimensions>{};
} else {
return blade_type_from_dimensions<A, mask_or_dimensions>{};
}
}())::type;
};

template <blade_ordering ord>
using blade_type_from_t = typename blade_type_from<ord>::type;
template <class A, auto mask_or_dimensions>
using blade_type_from_t = typename blade_type_from<A, mask_or_dimensions>::type;

/// @}

Expand Down
18 changes: 9 additions & 9 deletions rigid_geometric_algebra/sorted_canonical_blades.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "rigid_geometric_algebra/blade_ordering.hpp"
#include "rigid_geometric_algebra/blade_type_from.hpp"
#include "rigid_geometric_algebra/common_algebra_type.hpp"
#include "rigid_geometric_algebra/detail/array_subset.hpp"
#include "rigid_geometric_algebra/detail/has_type.hpp"
#include "rigid_geometric_algebra/detail/type_list.hpp"
#include "rigid_geometric_algebra/is_blade.hpp"
Expand Down Expand Up @@ -36,21 +37,20 @@ struct sorted_canonical_blades
{
using A = common_algebra_type_t<Bs...>;

static constexpr auto sorted_blades = [] {
auto values = std::array{
blade_ordering{std::type_identity<std::remove_cvref_t<Bs>>{}}...};
static constexpr auto sorted = [] {
auto values = std::array{blade_ordering{std::type_identity<Bs>{}}...};
std::ranges::sort(values);
auto subset = std::ranges::unique(values);
return std::pair{values, values.size() - subset.size()};
const auto duplicates = std::ranges::unique(values);
return detail::array_subset(values, values.size() - duplicates.size());
}();

static_assert(sorted_blades.second != 0);
static_assert(sorted.size() != 0);

template <std::size_t... Is>
static constexpr auto impl(std::index_sequence<Is...>) -> detail::type_list<
blade_type_from_t<std::get<Is>(sorted_blades.first)>...>;
static constexpr auto impl(std::index_sequence<Is...>)
-> detail::type_list<blade_type_from_t<A, sorted[Is].mask>...>;

using type = decltype(impl(std::make_index_sequence<sorted_blades.second>{}));
using type = decltype(impl(std::make_index_sequence<sorted.size()>{}));
};

template <>
Expand Down
10 changes: 4 additions & 6 deletions test/blade_type_from_test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#include "rigid_geometric_algebra/blade_ordering.hpp"
#include "rigid_geometric_algebra/rigid_geometric_algebra.hpp"
#include "skytest/skytest.hpp"

#include <type_traits>
#include <utility>

template <class Out, class In>
struct impl
Expand All @@ -12,12 +10,12 @@ struct impl
{
using ::rigid_geometric_algebra::algebra_type_t;
using ::rigid_geometric_algebra::blade_ordering;
using ::rigid_geometric_algebra::blade_type_from;
constexpr auto ord = blade_ordering{std::type_identity<In>{}};
using ::rigid_geometric_algebra::blade_type_from_t;

return Out{} ==
blade_type_from<ord>{}.impl(
std::make_index_sequence<ord.mask.count()>{});
blade_type_from_t<
algebra_type_t<In>,
blade_ordering{std::type_identity<In>{}}.mask>{};
}
};

Expand Down

0 comments on commit 663d8c7

Please sign in to comment.