Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7270afc93d2c
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: daf3bbf1b91e
Choose a head ref
  • 8 commits
  • 11 files changed
  • 1 contributor

Commits on Dec 26, 2019

  1. Copy the full SHA
    ad6e775 View commit details

Commits on Dec 27, 2019

  1. usages

    eggrobin committed Dec 27, 2019
    Copy the full SHA
    4cae87e View commit details
  2. include

    eggrobin committed Dec 27, 2019
    Copy the full SHA
    03456dc View commit details
  3. more usages

    eggrobin committed Dec 27, 2019
    Copy the full SHA
    b1740e4 View commit details
  4. Copy the full SHA
    8d8bb05 View commit details
  5. after pleroy's review

    eggrobin committed Dec 27, 2019
    Copy the full SHA
    9a3144b View commit details
  6. construct

    eggrobin committed Dec 27, 2019
    Copy the full SHA
    a5a29de View commit details
  7. Merge pull request #2413 from eggrobin/permutation-handedness

    Permutation handedness
    eggrobin authored Dec 27, 2019
    Copy the full SHA
    daf3bbf View commit details
56 changes: 37 additions & 19 deletions geometry/permutation.hpp
Original file line number Diff line number Diff line change
@@ -19,31 +19,47 @@ namespace internal_permutation {

using base::not_null;

// Declare shorter names for the protocol buffer enums.
static constexpr int EVEN = serialization::Permutation::EVEN;
static constexpr int ODD = serialization::Permutation::ODD;
static constexpr int X = serialization::Permutation::X;
static constexpr int Y = serialization::Permutation::Y;
static constexpr int Z = serialization::Permutation::Z;
static constexpr int INDEX = serialization::Permutation::INDEX;

static constexpr std::uint8_t COORDINATE_MASK = (1 << 2) - 1;
static constexpr std::uint8_t INDEX_MASK = (1 << 3) - 1;

static_assert((X & COORDINATE_MASK) == X);
static_assert((Y & COORDINATE_MASK) == Y);
static_assert((Z & COORDINATE_MASK) == Z);
static_assert(INDEX == 3 * 2);

// Danger, Will Robinson! These enums are stored in the serialized
// representation. Any change to the formulae below is likely to make it
// impossible to read existing files.
enum class EvenPermutation {
XYZ = EVEN + (X << X * 2) + (Y << Y * 2) + (Z << Z * 2) + (0 << INDEX),
YZX = EVEN + (Y << X * 2) + (Z << Y * 2) + (X << Z * 2) + (1 << INDEX),
ZXY = EVEN + (Z << X * 2) + (X << Y * 2) + (Y << Z * 2) + (2 << INDEX),
};

enum class OddPermutation {
XZY = ODD + (X << X * 2) + (Z << Y * 2) + (Y << Z * 2) + (3 << INDEX),
ZYX = ODD + (Z << X * 2) + (Y << Y * 2) + (X << Z * 2) + (4 << INDEX),
YXZ = ODD + (Y << X * 2) + (X << Y * 2) + (Z << Z * 2) + (5 << INDEX),
};

// A permutation of the coordinates. Obviously not coordinate-free, but
// practical. There are no precision losses when composing or applying
// permutations.
template<typename FromFrame, typename ToFrame>
class Permutation : public LinearMap<FromFrame, ToFrame> {
// Declare shorter names for the protocol buffer enums.
static int const EVEN = serialization::Permutation::EVEN;
static int const ODD = serialization::Permutation::ODD;
static int const X = serialization::Permutation::X;
static int const Y = serialization::Permutation::Y;
static int const Z = serialization::Permutation::Z;
static int const INDEX = serialization::Permutation::INDEX;

public:
// Danger, Will Robinson! This enum is stored in the serialized
// representation. Any change to the formulae below is likely to make it
// impossible to read existing files.
enum CoordinatePermutation {
XYZ = EVEN + (X << X * 2) + (Y << Y * 2) + (Z << Z * 2) + (0 << INDEX),
YZX = EVEN + (Y << X * 2) + (Z << Y * 2) + (X << Z * 2) + (1 << INDEX),
ZXY = EVEN + (Z << X * 2) + (X << Y * 2) + (Y << Z * 2) + (2 << INDEX),
XZY = ODD + (X << X * 2) + (Z << Y * 2) + (Y << Z * 2) + (3 << INDEX),
ZYX = ODD + (Z << X * 2) + (Y << Y * 2) + (X << Z * 2) + (4 << INDEX),
YXZ = ODD + (Y << X * 2) + (X << Y * 2) + (Z << Z * 2) + (5 << INDEX)
};
using CoordinatePermutation =
std::conditional_t<FromFrame::handedness == ToFrame::handedness,
EvenPermutation,
OddPermutation>;

explicit Permutation(CoordinatePermutation coordinate_permutation);

@@ -118,6 +134,8 @@ std::ostream& operator<<(std::ostream& out,

} // namespace internal_permutation

using internal_permutation::EvenPermutation;
using internal_permutation::OddPermutation;
using internal_permutation::Permutation;

} // namespace geometry
144 changes: 59 additions & 85 deletions geometry/permutation_body.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

#pragma once

#include <map>
#include <array>
#include <string>
#include <utility>

@@ -31,15 +31,16 @@ Permutation<ToFrame, FromFrame>
Permutation<FromFrame, ToFrame>::Inverse() const {
using PFT = Permutation<FromFrame, ToFrame>;
using PTF = Permutation<ToFrame, FromFrame>;
static std::map<PFT::CoordinatePermutation,
typename PTF::CoordinatePermutation> const inverse = {
{PFT::XYZ, PTF::XYZ},
{PFT::YZX, PTF::ZXY},
{PFT::ZXY, PTF::YZX},
{PFT::XZY, PTF::XZY},
{PFT::ZYX, PTF::ZYX},
{PFT::YXZ, PTF::YXZ}};
return PTF(inverse.at(coordinate_permutation_));
if constexpr (std::is_same_v<CoordinatePermutation, EvenPermutation>) {
static constexpr std::array<EvenPermutation, 3> inverse{
{EvenPermutation::XYZ, EvenPermutation::ZXY, EvenPermutation::YZX}};
return PTF(inverse[INDEX_MASK &
(static_cast<int>(coordinate_permutation_) >> INDEX)]);
} else {
// An odd permutation on three elements is a transposition, and thus is an
// involution.
return PTF(coordinate_permutation_);
}
}

template<typename FromFrame, typename ToFrame>
@@ -75,22 +76,24 @@ template<typename FromFrame, typename ToFrame>
OrthogonalMap<FromFrame, ToFrame>
Permutation<FromFrame, ToFrame>::Forget() const {
static double const sqrt_half = quantities::Sqrt(0.5);
static std::map<CoordinatePermutation, Quaternion> const quaternion = {
{XYZ, Quaternion(1, {0, 0, 0})},
{YZX, Quaternion(0.5, {-0.5, -0.5, -0.5})},
{ZXY, Quaternion(0.5, {0.5, 0.5, 0.5})},
{XZY, Quaternion(0, {0, -sqrt_half, sqrt_half})},
{ZYX, Quaternion(0, {-sqrt_half, 0, sqrt_half})},
{YXZ, Quaternion(0, {-sqrt_half, sqrt_half, 0})}};
static std::array<Quaternion, 6> const quaternion = {
/*XYZ*/ Quaternion(1),
/*YZX*/ Quaternion(0.5, {-0.5, -0.5, -0.5}),
/*ZXY*/ Quaternion(0.5, {0.5, 0.5, 0.5}),
/*XZY*/ Quaternion(0, {0, -sqrt_half, sqrt_half}),
/*ZYX*/ Quaternion(0, {-sqrt_half, 0, sqrt_half}),
/*YXZ*/ Quaternion(0, {-sqrt_half, sqrt_half, 0})};
return OrthogonalMap<FromFrame, ToFrame>(
Determinant(),
Rotation<FromFrame, ToFrame>(quaternion.at(coordinate_permutation_)));
Rotation<FromFrame, ToFrame>(
quaternion[INDEX_MASK &
(static_cast<int>(coordinate_permutation_) >> INDEX)]));
}

template<typename FromFrame, typename ToFrame>
template<typename F, typename T, typename>
Permutation<FromFrame, ToFrame> Permutation<FromFrame, ToFrame>::Identity() {
return Permutation(XYZ);
return Permutation(EvenPermutation::XYZ);
}

template<typename FromFrame, typename ToFrame>
@@ -115,7 +118,8 @@ Permutation<FromFrame, ToFrame>::ReadFromMessage(
template<typename FromFrame, typename ToFrame>
void Permutation<FromFrame, ToFrame>::WriteToMessage(
not_null<serialization::Permutation*> const message) const {
message->set_coordinate_permutation(coordinate_permutation_);
message->set_coordinate_permutation(
static_cast<int>(coordinate_permutation_));
}

template<typename FromFrame, typename ToFrame>
@@ -133,9 +137,10 @@ R3Element<Scalar> Permutation<FromFrame, ToFrame>::operator()(
R3Element<Scalar> const& r3_element) const {
R3Element<Scalar> result;
for (int coordinate = X; coordinate <= Z; ++coordinate) {
result[coordinate] = r3_element[
0x3 &
(static_cast<int>(coordinate_permutation_) >> (coordinate * 2))];
result[coordinate] =
r3_element[COORDINATE_MASK &
(static_cast<int>(coordinate_permutation_) >>
(coordinate * 2))];
}
return result;
}
@@ -144,74 +149,43 @@ template<typename FromFrame, typename ThroughFrame, typename ToFrame>
Permutation<FromFrame, ToFrame> operator*(
Permutation<ThroughFrame, ToFrame> const& left,
Permutation<FromFrame, ThroughFrame> const& right) {
using Left = Permutation<ThroughFrame, ToFrame>;
using Right = Permutation<FromFrame, ThroughFrame>;
using Result = Permutation<FromFrame, ToFrame>;

// The pair<> is in diagrammatic order: right is applied first and is the
// first element of the pair, left is applied second and is the second
// element.
static std::map<
std::pair<typename Right::CoordinatePermutation,
typename Left::CoordinatePermutation>,
typename Result::CoordinatePermutation> const multiplication = {
{{Right::XYZ, Left::XYZ}, Result::XYZ},
{{Right::XYZ, Left::YZX}, Result::YZX},
{{Right::XYZ, Left::ZXY}, Result::ZXY},
{{Right::XYZ, Left::XZY}, Result::XZY},
{{Right::XYZ, Left::ZYX}, Result::ZYX},
{{Right::XYZ, Left::YXZ}, Result::YXZ},

{{Right::YZX, Left::XYZ}, Result::YZX},
{{Right::YZX, Left::YZX}, Result::ZXY},
{{Right::YZX, Left::ZXY}, Result::XYZ},
{{Right::YZX, Left::XZY}, Result::YXZ},
{{Right::YZX, Left::ZYX}, Result::XZY},
{{Right::YZX, Left::YXZ}, Result::ZYX},

{{Right::ZXY, Left::XYZ}, Result::ZXY},
{{Right::ZXY, Left::YZX}, Result::XYZ},
{{Right::ZXY, Left::ZXY}, Result::YZX},
{{Right::ZXY, Left::XZY}, Result::ZYX},
{{Right::ZXY, Left::ZYX}, Result::YXZ},
{{Right::ZXY, Left::YXZ}, Result::XZY},

{{Right::XZY, Left::XYZ}, Result::XZY},
{{Right::XZY, Left::YZX}, Result::ZYX},
{{Right::XZY, Left::ZXY}, Result::YXZ},
{{Right::XZY, Left::XZY}, Result::XYZ},
{{Right::XZY, Left::ZYX}, Result::YZX},
{{Right::XZY, Left::YXZ}, Result::ZXY},

{{Right::ZYX, Left::XYZ}, Result::ZYX},
{{Right::ZYX, Left::YZX}, Result::YXZ},
{{Right::ZYX, Left::ZXY}, Result::XZY},
{{Right::ZYX, Left::XZY}, Result::ZXY},
{{Right::ZYX, Left::ZYX}, Result::XYZ},
{{Right::ZYX, Left::YXZ}, Result::YZX},

{{Right::YXZ, Left::XYZ}, Result::YXZ},
{{Right::YXZ, Left::YZX}, Result::XZY},
{{Right::YXZ, Left::ZXY}, Result::ZYX},
{{Right::YXZ, Left::XZY}, Result::YZX},
{{Right::YXZ, Left::ZYX}, Result::ZXY},
{{Right::YXZ, Left::YXZ}, Result::XYZ}};
return Result(multiplication.at({right.coordinate_permutation_,
left.coordinate_permutation_}));
struct AnyPermutation {
constexpr AnyPermutation(EvenPermutation value) // NOLINT(runtime/explicit)
: value(static_cast<int>(value)) {}
constexpr AnyPermutation(OddPermutation value) // NOLINT(runtime/explicit)
: value(static_cast<int>(value)) {}
int value;
};
using E = EvenPermutation;
using O = OddPermutation;
static constexpr std::array<std::array<AnyPermutation, 6>, 6> multiplication{{
/* XYZ, YZX, ZXY, XZY, ZYX, YXZ*/
/*XYZ*/ {E::XYZ, E::YZX, E::ZXY, O::XZY, O::ZYX, O::YXZ},
/*YZX*/ {E::YZX, E::ZXY, E::XYZ, O::ZYX, O::YXZ, O::XZY},
/*ZXY*/ {E::ZXY, E::XYZ, E::YZX, O::YXZ, O::XZY, O::ZYX},
/*XZY*/ {O::XZY, O::YXZ, O::ZYX, E::XYZ, E::ZXY, E::YZX},
/*ZYX*/ {O::ZYX, O::XZY, O::YXZ, E::YZX, E::XYZ, E::ZXY},
/*YXZ*/ {O::YXZ, O::ZYX, O::XZY, E::ZXY, E::YZX, E::XYZ},
}};

return Result(static_cast<Result::CoordinatePermutation>(
multiplication[INDEX_MASK &
(static_cast<int>(left.coordinate_permutation_) >> INDEX)]
[INDEX_MASK &
(static_cast<int>(right.coordinate_permutation_) >> INDEX)]
.value));
}

template<typename FromFrame, typename ToFrame>
std::ostream& operator<<(std::ostream& out,
Permutation<FromFrame, ToFrame> const& permutation) {
using PFT = Permutation<FromFrame, ToFrame>;
static std::map<typename PFT::CoordinatePermutation, std::string> const
debug_string = {{PFT::XYZ, "XYZ"},
{PFT::YZX, "YZX"},
{PFT::ZXY, "ZXY"},
{PFT::XZY, "XZY"},
{PFT::ZYX, "ZYX"},
{PFT::YXZ, "YXZ"}};
return out << debug_string.at(permutation.coordinate_permutation_);
static constexpr std::array<std::string_view, 6> debug_string{
{"XYZ", "YZX", "ZXY", "XZY", "ZYX", "YXZ"}};
return out << debug_string
[INDEX_MASK &
(static_cast<int>(permutation.coordinate_permutation_) >>
INDEX)];
}

} // namespace internal_permutation
Loading