Skip to content

Commit

Permalink
construct multivector from blade addition
Browse files Browse the repository at this point in the history
Change-Id: Ib2e5fd58c9fff51a15afb5814c48b97d180a311f
  • Loading branch information
oliverlee committed Jan 9, 2024
1 parent f92f598 commit 7c3aeda
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 120 deletions.
3 changes: 2 additions & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ cc_library(
"geometry/src/detail/all_same.hpp",
"geometry/src/detail/contract_dimensions.hpp",
"geometry/src/detail/ordered.hpp",
"geometry/src/detail/sort_dimensions.hpp",
"geometry/src/detail/strictly_increasing.hpp",
"geometry/src/detail/type_list.hpp",
"geometry/src/detail/type_sort.hpp",
],
hdrs = ["geometry/geometry.hpp"],
visibility = ["//visibility:public"],
Expand Down
55 changes: 40 additions & 15 deletions geometry/src/algebra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
#include "geometry/src/detail/all_same.hpp"
#include "geometry/src/detail/contract_dimensions.hpp"
#include "geometry/src/detail/ordered.hpp"
#include "geometry/src/detail/sort_dimensions.hpp"
#include "geometry/src/detail/strictly_increasing.hpp"
#include "geometry/src/detail/type_list.hpp"
#include "geometry/src/detail/type_sort.hpp"

#include <cstddef>
#include <type_traits>
Expand Down Expand Up @@ -35,6 +36,16 @@ struct algebra
template <std::size_t... Is>
struct blade;

/// multivector
/// @tparam Bs blade types
///
/// A linear combination of blades.
///
/// @note a multivector may be composed of only blades with the same grade
///
template <class... Bs>
struct multivector;

/// determines if a type is a blade
/// @tparam T type
///
Expand All @@ -50,25 +61,29 @@ struct algebra
/// @}

private:
template <std::size_t... Is>
static auto rebind(std::index_sequence<Is...>) -> blade<Is...>;
template <class... Is>
static auto rebind(detail::type_list<Is...>) -> blade<Is::value...>;

template <class Seq>
using rebind_t = decltype(rebind(Seq{}));

template <std::size_t... Is>
using sequence_t =
detail::type_list<std::integral_constant<std::size_t, Is>...>;

template <std::size_t... Is>
using reified_blade_t = rebind_t<detail::contract_dimensions_t<
detail::contraction_map::projective,
detail::sort_dimensions_t<std::index_sequence<Is...>>>>;
detail::type_sort_t<sequence_t<Is...>>>>;

template <std::size_t... Is>
static constexpr auto reified_blade_coefficient_v =
(detail::sort_dimensions_swap_count_v<std::index_sequence<Is...>> % 2 == 0
(detail::type_sort_swap_count_v<sequence_t<Is...>> % 2 == 0
? scalar_type{1}
: -scalar_type{1}) *
scalar_type{detail::contract_dimensions_coefficient_v<
detail::contraction_map::projective,
detail::sort_dimensions_t<std::index_sequence<Is...>>>};
detail::type_sort_t<sequence_t<Is...>>>};

public:
/// unit blade
Expand Down Expand Up @@ -190,21 +205,38 @@ struct algebra

/// addition
///
/// @{
[[nodiscard]]
friend constexpr auto
operator+(blade x, blade y) -> blade
{
return blade{x.coefficient + y.coefficient};
}
template <std::size_t... Js>
[[nodiscard]]
friend constexpr auto
operator+(blade x, blade<Js...> y)
{
if constexpr (
detail::ordered<blade<Js...>>{} < detail::ordered<blade>{}) {
return multivector<blade<Js...>, blade>{y, x};
} else {
return multivector<blade, blade<Js...>>{x, y};
}
}
/// @}

/// subtraction
///
/// @{
template <std::size_t... Js>
[[nodiscard]]
friend constexpr auto
operator-(blade x, blade y) -> blade
operator-(blade x, blade<Js...> y)
{
return blade{x.coefficient - y.coefficient};
return x + -y;
}
/// @}

/// scalar multiplication
///
Expand Down Expand Up @@ -234,13 +266,6 @@ struct algebra
}
};

/// multivector
/// @tparam Bs blade types
///
/// A linear combination of blades.
///
/// @note a multivector may be composed of only blades with the same grade
///
template <class... Bs>
struct multivector : Bs...
{
Expand Down
44 changes: 12 additions & 32 deletions geometry/src/detail/contract_dimensions.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "geometry/src/detail/type_list.hpp"

#include <cstddef>
#include <utility>

Expand All @@ -14,49 +16,27 @@ struct contraction_map
};
};

template <
class Map,
class InSeq,
int Coeff = 1,
class OutSeq = std::index_sequence<>>
template <class Map, class InSeq, int Coeff = 1, class OutSeq = type_list<>>
struct contract_dimensions
{
using type = OutSeq;
static constexpr auto coefficient = Coeff;
};
template <
class Map,
std::size_t I0,
std::size_t... Is,
int Coeff,
std::size_t... Js>
struct contract_dimensions<
Map,
std::index_sequence<I0, Is...>,
Coeff,
std::index_sequence<Js...>>
: contract_dimensions<
Map,
std::index_sequence<Is...>,
Coeff,
std::index_sequence<Js..., I0>>
template <class Map, class I0, class... Is, int Coeff, class... Js>
struct contract_dimensions<Map, type_list<I0, Is...>, Coeff, type_list<Js...>>
: contract_dimensions<Map, type_list<Is...>, Coeff, type_list<Js..., I0>>
{};
template <
class Map,
std::size_t I0,
std::size_t... Is,
int Coeff,
std::size_t... Js>
template <class Map, class I0, class... Is, int Coeff, class... Js>
struct contract_dimensions<
Map,
std::index_sequence<I0, I0, Is...>,
type_list<I0, I0, Is...>,
Coeff,
std::index_sequence<Js...>>
type_list<Js...>>
: contract_dimensions<
Map,
std::index_sequence<Is...>,
Coeff * Map::template value<I0>,
std::index_sequence<Js...>>
type_list<Is...>,
Coeff * Map::template value<I0{}>,
type_list<Js...>>
{};

template <class Map, class Seq>
Expand Down
68 changes: 0 additions & 68 deletions geometry/src/detail/sort_dimensions.hpp

This file was deleted.

9 changes: 9 additions & 0 deletions geometry/src/detail/type_list.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

namespace geometry::detail {

template <class...>
struct type_list
{};

} // namespace geometry::detail
64 changes: 64 additions & 0 deletions geometry/src/detail/type_sort.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

#include "geometry/src/detail/type_list.hpp"

#include <cstddef>
#include <type_traits>
#include <utility>

namespace geometry::detail {

template <class InSeq, class OutSeq = type_list<>>
struct sort_swap_first
{
using type = OutSeq;
};

template <class I0, class... Js>
struct sort_swap_first<type_list<I0>, type_list<Js...>>
{
using type = type_list<Js..., I0>;
};
template <class I0, class I1, class... Is, class... Js>
struct sort_swap_first<type_list<I0, I1, Is...>, type_list<Js...>>
: std::conditional_t<
(I0{} > I1{}),
sort_swap_first<type_list<>, type_list<Js..., I1, I0, Is...>>,
sort_swap_first<type_list<I1, Is...>, type_list<Js..., I0>>>
{};

template <class Seq>
using sort_swap_first_t = typename sort_swap_first<Seq>::type;

template <class Seq, std::size_t Swaps = 0, class = void>
struct sort_swap : sort_swap<sort_swap_first_t<Seq>, Swaps + 1>
{};
template <class... Is, std::size_t Swaps>
struct sort_swap<
type_list<Is...>,
Swaps,
std::enable_if_t<
std::is_same_v<type_list<Is...>, sort_swap_first_t<type_list<Is...>>>>>
{
using type = type_list<Is...>;
static constexpr auto swap_count = Swaps;
};

template <class Seq>
struct type_sort
{
using type = typename sort_swap<Seq>::type;
};

template <class Seq>
using type_sort_t = typename type_sort<Seq>::type;

template <class Seq>
struct type_sort_swap_count
: std::integral_constant<std::size_t, sort_swap<Seq>::swap_count>
{};

template <class Seq>
inline constexpr auto type_sort_swap_count_v = type_sort_swap_count<Seq>::value;

} // namespace geometry::detail
16 changes: 12 additions & 4 deletions test/algebra_multivector_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ constexpr auto e = ::geometry::algebra<double, 2>::e<Is...>;
inline constexpr struct
{
template <
class... Bs,
class = std::enable_if_t<
sizeof...(Bs) != 0 and
::geometry::detail::all_same_v<typename Bs::algebra_type...>>>
class... Bs,
class = std::enable_if_t<
sizeof...(Bs) != 0 and
::geometry::detail::all_same_v<typename Bs::algebra_type...>>>
[[nodiscard]]
constexpr auto
operator()(Bs... bs) const
Expand Down Expand Up @@ -43,4 +43,12 @@ auto main() -> int
"multivector with same elements comparable"_ctest *
param_ref<multivectors> = //
[](auto v) { return expect(eq(v, v)); };

"multivector constructible from blade addition"_ctest = //
[] {
return expect(
eq(multivector(2 * e<0>, 3 * e<1>), 2 * e<0> + 3 * e<1>) and
eq(multivector(2 * e<0>, 3 * e<1>), 3 * e<1> + 2 * e<0>) and
eq(multivector(-2 * e<0>, 3 * e<1>), 3 * e<1> - 2 * e<0>));
};
}

0 comments on commit 7c3aeda

Please sign in to comment.