Skip to content

Commit

Permalink
define algebra multivector type
Browse files Browse the repository at this point in the history
Change-Id: I6abd8a67a3b94f537b705da8b1a1f7179d5426f7
  • Loading branch information
oliverlee committed Jan 12, 2024
1 parent b94454f commit 063b7ca
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 44 deletions.
4 changes: 3 additions & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ cc_library(
name = "geometry",
srcs = [
"geometry/src/algebra.hpp",
"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/unique_sorted.hpp",
"geometry/src/detail/strictly_increasing.hpp",
],
hdrs = ["geometry/geometry.hpp"],
visibility = ["//visibility:public"],
Expand Down
66 changes: 64 additions & 2 deletions geometry/src/algebra.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once

#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/unique_sorted.hpp"
#include "geometry/src/detail/strictly_increasing.hpp"

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

/// determines if a type is a blade
/// @tparam T type
///
/// @{
template <class T>
struct is_blade : std::false_type
{};
template <std::size_t... Is>
struct is_blade<blade<Is...>> : std::true_type
{};
template <class T>
static constexpr auto is_blade_v = is_blade<T>::value;
/// @}

private:
template <std::size_t... Is>
static auto rebind(std::index_sequence<Is...>) -> blade<Is...>;
Expand Down Expand Up @@ -86,7 +102,8 @@ struct algebra
static_assert(sizeof...(Is) <= N + 1, "number of `Is` exceeds rank");
static_assert(((Is <= N) and ...), "`Is` value exceeds rank");
static_assert(
detail::unique_sorted(Is...), "`Is` values must be unique and sorted");
detail::strictly_increasing(Is...),
"`Is` values must be unique and sorted");

/// algebra type
///
Expand Down Expand Up @@ -216,6 +233,51 @@ struct algebra
return x.coefficient * y.coefficient * e<Is..., Js...>;
}
};

/// 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...
{
static_assert(
(is_blade_v<Bs> and ...), "`Bs` must be a specialization of blade");
static_assert(
detail::all_same_v<typename Bs::scalar_type...>,
"`Bs` must have the same scalar type");
static_assert(
detail::strictly_increasing(detail::ordered<Bs>{}...),
"`Bs` must be lexicographically sorted");

/// algebra type
///
using algebra_type = algebra;

/// construct a multivector from blades
///
constexpr multivector(Bs... bs) : Bs{bs}... {}

/// equality comparison
///
/// @{
[[nodiscard]]
friend constexpr auto
operator==(const multivector& x, const multivector& y) -> bool
{
return ((static_cast<const Bs&>(x) == static_cast<const Bs&>(y)) and ...);
}
[[nodiscard]]
friend constexpr auto
operator!=(const multivector& x, const multivector& y) -> bool
{
return not(x == y);
}
/// @}
};
};

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

#include <type_traits>

namespace geometry::detail {

template <class...>
struct all_same : std::false_type
{};

template <>
struct all_same<> : std::true_type
{};
template <class T>
struct all_same<T> : std::true_type
{};
template <class T, class... Ts>
struct all_same<T, Ts...> : std::bool_constant<((std::is_same_v<T, Ts>)and...)>
{};

template <class... Ts>
inline constexpr auto all_same_v = all_same<Ts...>::value;

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

namespace geometry::detail {

template <class B>
class ordered
{
template <
template <std::size_t...>
class blade,
std::size_t... Is,
std::size_t... Js>
static constexpr auto
compare_dimensions(ordered<blade<Is...>>, ordered<blade<Js...>>)
{
return std::tuple{Is...} < std::tuple{Js...};
}

template <class B2>
friend constexpr auto operator<(ordered x, ordered<B2> y) -> bool
{
if constexpr (B::grade == B2::grade) {
return compare_dimensions(x, y);
} else {
return B::grade < B2::grade;
}
}
};

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

#include <cstddef>
#include <tuple>
#include <utility>

namespace geometry::detail {

inline constexpr class
{
template <std::size_t... Is, class T>
static constexpr auto impl(std::index_sequence<Is...>, const T& values)
{
if constexpr (sizeof...(Is) == 0) {
return true;
} else {
return ((std::get<Is>(values) < std::get<Is + 1>(values)) and ...);
}
}

public:
// 0-args
constexpr auto operator()() const { return true; }
// 1+-args
template <class T0, class... Ts>
constexpr auto operator()(T0 t0, Ts... ts) const
{
return impl(std::index_sequence_for<Ts...>{}, std::tuple{t0, ts...});
}
} strictly_increasing{};

} // namespace geometry::detail
39 changes: 0 additions & 39 deletions geometry/src/detail/unique_sorted.hpp

This file was deleted.

13 changes: 11 additions & 2 deletions test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
load("@rules_cc//cc:defs.bzl", "cc_test")

cc_test(
name = "algebra_test",
srcs = ["algebra_test.cpp"],
name = "algebra_blade_test",
srcs = ["algebra_blade_test.cpp"],
deps = [
"//:geometry",
"@skytest",
],
)

cc_test(
name = "algebra_multivector_test",
srcs = ["algebra_multivector_test.cpp"],
deps = [
"//:geometry",
"@skytest",
Expand Down
File renamed without changes.
46 changes: 46 additions & 0 deletions test/algebra_multivector_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "geometry/geometry.hpp"
#include "skytest/skytest.hpp"

#include <tuple>

template <std::size_t... Is>
constexpr auto e = ::geometry::algebra<double, 2>::e<Is...>;

/// construct a multivector from blades
///
inline constexpr struct
{
template <
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
{
using Algebra = std::common_type_t<typename Bs::algebra_type...>;
return typename Algebra::template multivector<Bs...>{bs...};
}
} multivector{};

auto main() -> int
{
using namespace ::skytest::literals;
using ::skytest::eq;
using ::skytest::expect;
using ::skytest::param_ref;

static constexpr auto multivectors = std::tuple{
multivector(e<>),
multivector(e<>, e<0>),
multivector(e<>, e<1>),
multivector(e<>, e<2>),
multivector(e<>, e<0>, e<1, 2>),
multivector(e<>, e<0, 1>, e<1, 2>),
multivector(e<>, e<0, 1, 2>)};

"multivector with same elements comparable"_ctest *
param_ref<multivectors> = //
[](auto v) { return expect(eq(v, v)); };
}

0 comments on commit 063b7ca

Please sign in to comment.