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: f3d4abd8470d
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8fabcf606317
Choose a head ref
  • 8 commits
  • 24 files changed
  • 1 contributor

Commits on Nov 13, 2019

  1. sign bit

    eggrobin committed Nov 13, 2019
    Copy the full SHA
    b372d33 View commit details
  2. rename the predicates

    eggrobin committed Nov 13, 2019
    Copy the full SHA
    878c51c View commit details
  3. Copy the full SHA
    36958a3 View commit details

Commits on Nov 14, 2019

  1. constexpr

    eggrobin committed Nov 14, 2019
    Copy the full SHA
    9279ec8 View commit details

Commits on Nov 15, 2019

  1. after pleroy's review

    eggrobin committed Nov 15, 2019
    Copy the full SHA
    fe19db5 View commit details

Commits on Nov 16, 2019

  1. line length

    eggrobin committed Nov 16, 2019
    Copy the full SHA
    735c990 View commit details
  2. merge

    eggrobin committed Nov 16, 2019
    Copy the full SHA
    eb3408e View commit details
  3. Merge pull request #2372 from eggrobin/much-ado-about-nothing’s-sign-bit

    Much ado about nothing’s sign bit
    eggrobin authored Nov 16, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8fabcf6 View commit details
2 changes: 1 addition & 1 deletion astronomy/ksp_resonance_test.cpp
Original file line number Diff line number Diff line change
@@ -191,7 +191,7 @@ class KSPResonanceTest : public ::testing::Test {
};

Instant t1 = t;
Sign s0(0);
Sign s0 = Sign::Positive();
if (t1 <= ephemeris.t_max()) {
s0 = Sign(moon_y(t1));
}
2 changes: 1 addition & 1 deletion astronomy/ksp_system_test.cpp
Original file line number Diff line number Diff line change
@@ -234,7 +234,7 @@ TEST_F(KSPSystemTest, KerbalSystem) {
std::vector<double> pol_bop_separations_in_m;

for (not_null<MassiveBody const*> const moon : joolian_moons_) {
last_separation_changes.emplace(moon, Sign(+1));
last_separation_changes.emplace(moon, Sign::Positive());
}
for (int n = 0;
t < a_century_hence;
4 changes: 2 additions & 2 deletions astronomy/lunar_eclipse_test.cpp
Original file line number Diff line number Diff line change
@@ -54,8 +54,8 @@ namespace {

Time const bisection_interval = 10 * Minute;

Sign const U14 = Sign(1);
Sign const U23 = Sign(-1);
Sign const U14 = Sign::Positive();
Sign const U23 = Sign::Negative();

char const arrow[] = "-------------------> ";

4 changes: 2 additions & 2 deletions astronomy/orbit_recurrence_body.hpp
Original file line number Diff line number Diff line change
@@ -22,13 +22,13 @@ inline OrbitRecurrence::OrbitRecurrence(int const νₒ,
int const Cᴛₒ)
: νₒ_(νₒ), Dᴛₒ_(Dᴛₒ), Cᴛₒ_(Cᴛₒ) {
CHECK_NE(Cᴛₒ, 0) << *this;
Sign const sign_Cᴛₒ = Sign::OfNonZero(Cᴛₒ);
if (νₒ != 0) {
CHECK_EQ(Sign(νₒ), Sign(Cᴛₒ)) << *this;
CHECK_EQ(Sign::OfNonZero(νₒ), sign_Cᴛₒ) << *this;
}
CHECK_LE(Abs(2 * Dᴛₒ), Abs(Cᴛₒ)) << *this;
CHECK_EQ(std::gcd(Dᴛₒ, Cᴛₒ), 1) << *this;

int const sign_Cᴛₒ = Sign(Cᴛₒ) * 1;
int& Eᴛₒ = subcycle_;
if (Dᴛₒ == 0) {
Eᴛₒ = 0;
4 changes: 2 additions & 2 deletions astronomy/trappist_dynamics_test.cpp
Original file line number Diff line number Diff line change
@@ -1029,8 +1029,8 @@ class TrappistDynamicsTest : public ::testing::Test {
Sign const xy_displacement_derivative_sign(xy_displacement_derivative(t));
if (relative_dof.displacement().coordinates().z > 0.0 * Metre &&
last_t &&
xy_displacement_derivative_sign == Sign(1) &&
last_xy_displacement_derivative_sign == Sign(-1)) {
xy_displacement_derivative_sign.is_positive() &&
last_xy_displacement_derivative_sign == Sign::Negative()) {
Instant const transit = Bisect(xy_displacement_derivative, *last_t, t);
transits.push_back(transit);
}
2 changes: 1 addition & 1 deletion geometry/identity_body.hpp
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ Identity<FromFrame, ToFrame>::Identity() {}

template<typename FromFrame, typename ToFrame>
Sign Identity<FromFrame, ToFrame>::Determinant() const {
return Sign(1);
return Sign::Positive();
}

template<typename FromFrame, typename ToFrame>
2 changes: 1 addition & 1 deletion geometry/identity_test.cpp
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ class IdentityTest : public testing::Test {
using IdentityDeathTest = IdentityTest;

TEST_F(IdentityTest, Determinant) {
EXPECT_TRUE(Id().Determinant().Positive());
EXPECT_TRUE(Id().Determinant().is_positive());
}

TEST_F(IdentityTest, AppliedToVector) {
3 changes: 2 additions & 1 deletion geometry/orthogonal_map_body.hpp
Original file line number Diff line number Diff line change
@@ -66,7 +66,8 @@ OrthogonalMap<FromFrame, ToFrame>::operator()(T const& t) const {
template<typename FromFrame, typename ToFrame>
OrthogonalMap<FromFrame, ToFrame>
OrthogonalMap<FromFrame, ToFrame>::Identity() {
return OrthogonalMap(Sign(1), Rotation<FromFrame, ToFrame>::Identity());
return OrthogonalMap(Sign::Positive(),
Rotation<FromFrame, ToFrame>::Identity());
}

template<typename FromFrame, typename ToFrame>
18 changes: 9 additions & 9 deletions geometry/orthogonal_map_test.cpp
Original file line number Diff line number Diff line change
@@ -36,13 +36,13 @@ class OrthogonalMapTest : public testing::Test {
R3Element<quantities::Length>(
1.0 * Metre, 2.0 * Metre, 3.0 * Metre))),
trivector_(Trivector<quantities::Length, World>(4.0 * Metre)),
orthogonal_a_(Orth(Sign(-1),
orthogonal_a_(Orth(Sign::Negative(),
Rot(120 * Degree,
Bivector<double, World>({1, 1, 1})))),
orthogonal_b_(Orth(Sign(1),
orthogonal_b_(Orth(Sign::Positive(),
Rot(90 * Degree,
Bivector<double, World>({1, 0, 0})))),
orthogonal_c_(Orth(Sign(-1),
orthogonal_c_(Orth(Sign::Negative(),
Rot(90 * Degree,
Bivector<double, World>({1, 0, 0})))) {}

@@ -98,9 +98,9 @@ TEST_F(OrthogonalMapTest, AppliedToTrivector) {
}

TEST_F(OrthogonalMapTest, Determinant) {
EXPECT_TRUE(orthogonal_a_.Determinant().Negative());
EXPECT_TRUE(orthogonal_b_.Determinant().Positive());
EXPECT_TRUE(orthogonal_c_.Determinant().Negative());
EXPECT_TRUE(orthogonal_a_.Determinant().is_negative());
EXPECT_TRUE(orthogonal_b_.Determinant().is_positive());
EXPECT_TRUE(orthogonal_c_.Determinant().is_negative());
}

TEST_F(OrthogonalMapTest, Inverse) {
@@ -123,9 +123,9 @@ TEST_F(OrthogonalMapTest, Composition) {
R3Element<quantities::Length>(2.0 * Metre,
1.0 * Metre,
-3.0 * Metre)), 4, 6));
EXPECT_TRUE((orthogonal_a_ * orthogonal_b_).Determinant().Negative());
EXPECT_TRUE((orthogonal_a_ * orthogonal_c_).Determinant().Positive());
EXPECT_TRUE((orthogonal_b_ * orthogonal_c_).Determinant().Negative());
EXPECT_TRUE((orthogonal_a_ * orthogonal_b_).Determinant().is_negative());
EXPECT_TRUE((orthogonal_a_ * orthogonal_c_).Determinant().is_positive());
EXPECT_TRUE((orthogonal_b_ * orthogonal_c_).Determinant().is_negative());
}

TEST_F(OrthogonalMapDeathTest, SerializationError) {
2 changes: 1 addition & 1 deletion geometry/permutation_body.hpp
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ Permutation<FromFrame, ToFrame>::Permutation(

template<typename FromFrame, typename ToFrame>
inline Sign Permutation<FromFrame, ToFrame>::Determinant() const {
return Sign(coordinate_permutation_);
return Sign::OfNonZero(static_cast<int>(coordinate_permutation_));
}

template<typename FromFrame, typename ToFrame>
12 changes: 6 additions & 6 deletions geometry/permutation_test.cpp
Original file line number Diff line number Diff line change
@@ -90,12 +90,12 @@ TEST_F(PermutationTest, Determinant) {
Perm xzy(Perm::XZY);
Perm zyx(Perm::ZYX);
Perm yxz(Perm::YXZ);
EXPECT_TRUE(xyz.Determinant().Positive());
EXPECT_TRUE(yzx.Determinant().Positive());
EXPECT_TRUE(zxy.Determinant().Positive());
EXPECT_TRUE(xzy.Determinant().Negative());
EXPECT_TRUE(zyx.Determinant().Negative());
EXPECT_TRUE(yxz.Determinant().Negative());
EXPECT_TRUE(xyz.Determinant().is_positive());
EXPECT_TRUE(yzx.Determinant().is_positive());
EXPECT_TRUE(zxy.Determinant().is_positive());
EXPECT_TRUE(xzy.Determinant().is_negative());
EXPECT_TRUE(zyx.Determinant().is_negative());
EXPECT_TRUE(yxz.Determinant().is_negative());
}

TEST_F(PermutationTest, AppliedToVector) {
4 changes: 2 additions & 2 deletions geometry/rotation_body.hpp
Original file line number Diff line number Diff line change
@@ -178,7 +178,7 @@ Rotation<FromFrame, ToFrame>::Rotation(

template<typename FromFrame, typename ToFrame>
Sign Rotation<FromFrame, ToFrame>::Determinant() const {
return Sign(1);
return Sign::Positive();
}

template<typename FromFrame, typename ToFrame>
@@ -265,7 +265,7 @@ Rotation<FromFrame, ToFrame>::operator()(T const& t) const {

template<typename FromFrame, typename ToFrame>
OrthogonalMap<FromFrame, ToFrame> Rotation<FromFrame, ToFrame>::Forget() const {
return OrthogonalMap<FromFrame, ToFrame>(Sign(1), *this);
return OrthogonalMap<FromFrame, ToFrame>(Sign::Positive(), *this);
}

template<typename FromFrame, typename ToFrame>
6 changes: 3 additions & 3 deletions geometry/rotation_test.cpp
Original file line number Diff line number Diff line change
@@ -146,9 +146,9 @@ TEST_F(RotationTest, AppliedToSymmetricBilinearForm) {
}

TEST_F(RotationTest, Determinant) {
EXPECT_TRUE(rotation_a_.Determinant().Positive());
EXPECT_TRUE(rotation_b_.Determinant().Positive());
EXPECT_TRUE(rotation_c_.Determinant().Positive());
EXPECT_TRUE(rotation_a_.Determinant().is_positive());
EXPECT_TRUE(rotation_b_.Determinant().is_positive());
EXPECT_TRUE(rotation_c_.Determinant().is_positive());
}

TEST_F(RotationTest, Inverse) {
50 changes: 38 additions & 12 deletions geometry/sign.hpp
Original file line number Diff line number Diff line change
@@ -4,45 +4,71 @@
#include <string>

#include "base/not_null.hpp"
#include "quantities/quantities.hpp"
#include "serialization/geometry.pb.h"

namespace principia {
namespace geometry {
namespace internal_sign {

using base::not_null;
using quantities::Quantity;

// An element of the multiplicative group ({+1, -1}, *). Useful for instance to
// represent the determinant of an orthogonal map.
class Sign final {
public:
template<typename Scalar> explicit Sign(Scalar const& s);
explicit Sign(double x);

bool Negative() const;
bool Positive() const;
template<typename Dimensions>
explicit Sign(Quantity<Dimensions> const& x);

bool operator==(Sign const& other) const;
bool operator!=(Sign const& other) const;
// The deleted constructor forbids construction from an integer via
// integer-to-double conversion. Integers have no signed 0, so this could
// lead to confusing behaviour.
template<typename T>
explicit Sign(T x) = delete;

static constexpr Sign Positive();
static constexpr Sign Negative();

template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
static constexpr Sign OfNonZero(T x);

constexpr bool is_positive() const;
constexpr bool is_negative() const;

constexpr Sign operator+() const;
constexpr Sign operator-() const;

// Returns ±1.
constexpr operator int() const;

constexpr bool operator==(Sign other) const;
constexpr bool operator!=(Sign other) const;

void WriteToMessage(not_null<serialization::Sign*> message) const;
static Sign ReadFromMessage(serialization::Sign const& message);
static Sign ReadFromMessage(serialization::Sign message);

private:
constexpr explicit Sign(bool negative);

bool negative_;
friend Sign operator*(Sign const& left, Sign const& right);

friend constexpr Sign operator*(Sign left, Sign right);
template<typename T>
friend T operator*(Sign const& left, T const& right);
friend constexpr T operator*(Sign left, T const& right);
};

Sign operator*(Sign const& left, Sign const& right);
constexpr Sign operator*(Sign left, Sign right);

// This operator is applicable to any type that has a unary minus operator.
template<typename T>
T operator*(Sign const& left, T const& right);
constexpr T operator*(Sign left, T const& right);

std::string DebugString(Sign const& sign);
std::string DebugString(Sign sign);

std::ostream& operator<<(std::ostream& out, Sign const& sign);
std::ostream& operator<<(std::ostream& out, Sign sign);

} // namespace internal_sign

65 changes: 50 additions & 15 deletions geometry/sign_body.hpp
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@

#include "geometry/sign.hpp"

#include <cmath>
#include <string>

#include "base/macros.hpp"
@@ -11,22 +12,54 @@ namespace principia {
namespace geometry {
namespace internal_sign {

template<typename Scalar>
Sign::Sign(Scalar const& scalar) : negative_(scalar < Scalar{}) {}
using quantities::SIUnit;

inline bool Sign::Negative() const {
return negative_;
// TODO(egg): Consider intrinsics.
inline Sign::Sign(double const x) : negative_(std::signbit(x)) {}

template<typename Dimensions>
Sign::Sign(Quantity<Dimensions> const& x)
: Sign(x / SIUnit<Quantity<Dimensions>>()) {}

template<typename T, typename>
constexpr Sign Sign::OfNonZero(T x) {
CONSTEXPR_CHECK(x != 0) << x;
return Sign(/*negative=*/x < 0);
}

constexpr Sign Sign::Positive() {
return Sign(/*negative=*/false);
}

inline bool Sign::Positive() const {
constexpr Sign Sign::Negative() {
return Sign(/*negative=*/true);
}

constexpr bool Sign::is_positive() const {
return !negative_;
}

inline bool Sign::operator==(Sign const& other) const {
constexpr bool Sign::is_negative() const {
return negative_;
}

inline constexpr Sign Sign::operator+() const {
return *this;
}

inline constexpr Sign Sign::operator-() const {
return Sign(!negative_);
}

inline constexpr Sign::operator int() const {
return *this * 1;
}

constexpr bool Sign::operator==(Sign const other) const {
return negative_ == other.negative_;
}

inline bool Sign::operator!=(Sign const& other) const {
constexpr bool Sign::operator!=(Sign const other) const {
return negative_ != other.negative_;
}

@@ -35,24 +68,26 @@ inline void Sign::WriteToMessage(
message->set_negative(negative_);
}

inline Sign Sign::ReadFromMessage(serialization::Sign const& message) {
return Sign(message.negative() ? -1 : 1);
inline Sign Sign::ReadFromMessage(serialization::Sign const message) {
return Sign(/*negative=*/message.negative());
}

inline Sign operator*(Sign const& left, Sign const& right) {
return Sign(left.negative_ == right.negative_ ? 1 : -1);
constexpr Sign::Sign(bool const negative) : negative_(negative) {}

constexpr Sign operator*(Sign const left, Sign const right) {
return Sign(/*negative=*/left.negative_ != right.negative_);
}

template<typename T>
FORCE_INLINE(inline) T operator*(Sign const& left, T const& right) {
constexpr T operator*(Sign const left, T const& right) {
return left.negative_ ? -right : right;
}

inline std::string DebugString(Sign const& sign) {
return sign.Negative() ? "-" : "+";
inline std::string DebugString(Sign const sign) {
return sign.is_negative() ? "-" : "+";
}

inline std::ostream& operator<<(std::ostream& out, Sign const& sign) {
inline std::ostream& operator<<(std::ostream& out, Sign const sign) {
out << DebugString(sign);
return out;
}
Loading