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

Commits on Feb 19, 2018

  1. An awkward approach.

    pleroy committed Feb 19, 2018
    Copy the full SHA
    8add4ea View commit details
  2. Drop FromM128D.

    pleroy committed Feb 19, 2018
    Copy the full SHA
    5c7ffcc View commit details
  3. Remove useless stuff.

    pleroy committed Feb 19, 2018
    Copy the full SHA
    d719b4b View commit details

Commits on Feb 20, 2018

  1. After egg's review.

    pleroy committed Feb 20, 2018
    Copy the full SHA
    ba75b1f View commit details
  2. Merge pull request #1730 from pleroy/Wide

    A new class, Wide, to hold a 128-bit SSE representation of a quantity or double
    pleroy authored Feb 20, 2018
    Copy the full SHA
    fa897ff View commit details
3 changes: 2 additions & 1 deletion geometry/r3_element_body.hpp
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
#include "quantities/elementary_functions.hpp"
#include "quantities/quantities.hpp"
#include "quantities/serialization.hpp"
#include "quantities/wide.hpp"

#define PRINCIPIA_USE_SSE2_INTRINSICS 1

@@ -25,11 +26,11 @@ using quantities::ArcTan;
using quantities::Cos;
using quantities::DebugString;
using quantities::DoubleOrQuantitySerializer;
using quantities::FromM128D;
using quantities::Quantity;
using quantities::Sin;
using quantities::SIUnit;
using quantities::ToM128D;
using quantities::Wide;

// We want zero initialization here, so the default constructor won't do.
template<typename Scalar>
2 changes: 1 addition & 1 deletion quantities/generators.hpp
Original file line number Diff line number Diff line change
@@ -27,4 +27,4 @@ struct QuotientGenerator;
} // namespace principia

// Because of circular dependencies, this file doesn't include
// generators_body.hpp. This will be done by quantities_body.hpp.
// generators_body.hpp. This will be done by quantities.hpp.
26 changes: 9 additions & 17 deletions quantities/quantities.hpp
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
#include "quantities/dimensions.hpp"
#include "quantities/generators.hpp"
#include "quantities/traits.hpp"
#include "quantities/wide.hpp"
#include "serialization/quantities.pb.h"

namespace principia {
@@ -106,10 +107,9 @@ class Quantity final {
friend constexpr Q NaN();
template<typename Q>
friend constexpr Q SIUnit();
template<typename D>
friend Quantity<D> FromM128D(__m128d x);
template<typename D>
friend __m128d ToM128D(Quantity<D> x);

template<typename U>
friend __m128d internal_wide::ToM128D(Quantity<U> x);
};

template<typename LDimensions, typename RDimensions>
@@ -133,17 +133,6 @@ constexpr Q SIUnit();
template<>
constexpr double SIUnit<double>();

// Conversion to and from intrinsic types. ToM128D fills both halves of the
// result.
template<typename D>
Quantity<D> FromM128D(__m128d x);
template<typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
T FromM128D(__m128d x);
template<typename D>
__m128d ToM128D(Quantity<D> x);
template<typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
__m128d ToM128D(T x);

// Returns a positive infinity of |Q|.
template<typename Q>
constexpr Q Infinity();
@@ -171,7 +160,6 @@ using internal_quantities::Amount;
using internal_quantities::Angle;
using internal_quantities::Current;
using internal_quantities::DebugString;
using internal_quantities::FromM128D;
using internal_quantities::Infinity;
using internal_quantities::IsFinite;
using internal_quantities::Length;
@@ -182,9 +170,13 @@ using internal_quantities::Quantity;
using internal_quantities::SIUnit;
using internal_quantities::Temperature;
using internal_quantities::Time;
using internal_quantities::ToM128D;

} // namespace quantities
} // namespace principia

// Include before quantities_body.hpp all the bodies that want to see the
// definition of class Quantity.
#include "quantities/generators_body.hpp"
#include "quantities/wide_body.hpp"

#include "quantities/quantities_body.hpp"
3 changes: 3 additions & 0 deletions quantities/quantities.vcxproj
Original file line number Diff line number Diff line change
@@ -30,10 +30,13 @@
<ClInclude Include="si_body.hpp" />
<ClInclude Include="traits.hpp" />
<ClInclude Include="uk.hpp" />
<ClInclude Include="wide.hpp" />
<ClInclude Include="wide_body.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="elementary_functions_test.cpp" />
<ClCompile Include="parser_test.cpp" />
<ClCompile Include="quantities_test.cpp" />
<ClCompile Include="wide_test.cpp" />
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions quantities/quantities.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -80,6 +80,12 @@
<ClInclude Include="traits.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wide.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wide_body.hpp">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="quantities_test.cpp">
@@ -91,5 +97,8 @@
<ClCompile Include="elementary_functions_test.cpp">
<Filter>Test Files</Filter>
</ClCompile>
<ClCompile Include="wide_test.cpp">
<Filter>Test Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
21 changes: 0 additions & 21 deletions quantities/quantities_body.hpp
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@
#include <string>

#include "base/macros.hpp"
#include "quantities/generators_body.hpp" // Apologies.

namespace principia {
namespace quantities {
@@ -173,26 +172,6 @@ constexpr double SIUnit<double>() {
return 1;
}

template<typename D>
Quantity<D> FromM128D(__m128d const x) {
return Quantity<D>(_mm_cvtsd_f64(x));
}

template<typename T, typename>
T FromM128D(__m128d const x) {
return static_cast<T>(_mm_cvtsd_f64(x));
}

template<typename D>
__m128d ToM128D(Quantity<D> const x) {
return _mm_set1_pd(x.magnitude_);
}

template<typename T, typename>
inline __m128d ToM128D(T const x) {
return _mm_set1_pd(static_cast<double>(x));
}

template<typename Q>
constexpr Q Infinity() {
return SIUnit<Q>() * std::numeric_limits<double>::infinity();
55 changes: 55 additions & 0 deletions quantities/wide.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

#pragma once

#include <nmmintrin.h>

#include <type_traits>

#include "base/not_constructible.hpp"
#include "quantities/traits.hpp"

namespace principia {
namespace quantities {

namespace internal_quantities {
template<typename D>
class Quantity;
} // namespace internal_quantities

namespace internal_wide {

using base::not_constructible;
using internal_quantities::Quantity;

// A wrapper for a quantity copied to all entries of a SIMD vector.
template<typename T>
class Wide final {
static_assert(is_quantity<T>::value, "Not a quantity type");
public:
explicit Wide(T x);

private:
__m128d wide_;

template<typename U>
friend __m128d ToM128D(Wide<U> x);
};

// Fills both halves of the result.
template<typename D>
__m128d ToM128D(Quantity<D> x);
template<typename T>
__m128d ToM128D(Wide<T> x);
template<typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
__m128d ToM128D(T x);

} // namespace internal_wide

using internal_wide::ToM128D;
using internal_wide::Wide;

} // namespace quantities
} // namespace principia

// Because of circular dependencies, this file doesn't include wide_body.hpp.
// This will be done by quantities.hpp.
30 changes: 30 additions & 0 deletions quantities/wide_body.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

#pragma once

#include "quantities/wide.hpp"

namespace principia {
namespace quantities {
namespace internal_wide {

template<typename T>
Wide<T>::Wide(T const x) : wide_(ToM128D(x)) {}

template<typename D>
__m128d ToM128D(Quantity<D> const x) {
return _mm_set1_pd(x.magnitude_);
}

template<typename T>
__m128d ToM128D(Wide<T> x) {
return x.wide_;
}

template<typename T, typename>
inline __m128d ToM128D(T const x) {
return _mm_set1_pd(static_cast<double>(x));
}

} // namespace internal_wide
} // namespace quantities
} // namespace principia
40 changes: 40 additions & 0 deletions quantities/wide_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

#include "quantities/wide.hpp"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "quantities/si.hpp"
#include "testing_utilities/matchers.hpp"

namespace principia {
namespace quantities {

using si::Metre;
using testing_utilities::SSEHighHalfIs;
using testing_utilities::SSELowHalfIs;
using ::testing::Eq;

TEST(WideTest, Conversions) {
Wide<Length> const w1(2 * Metre);
__m128d m1 = ToM128D(w1);
EXPECT_THAT(m1, SSEHighHalfIs(2));
EXPECT_THAT(m1, SSELowHalfIs(2));

Wide<double> const w2(3.14);
__m128d m2 = ToM128D(w2);
EXPECT_THAT(m2, SSEHighHalfIs(3.14));
EXPECT_THAT(m2, SSELowHalfIs(3.14));

Length const n3(3 * Metre);
__m128d m3 = ToM128D(n3);
EXPECT_THAT(m3, SSEHighHalfIs(3));
EXPECT_THAT(m3, SSELowHalfIs(3));

double const n4(2.71);
__m128d m4 = ToM128D(n4);
EXPECT_THAT(m4, SSEHighHalfIs(2.71));
EXPECT_THAT(m4, SSELowHalfIs(2.71));
}

} // namespace quantities
} // namespace principia
17 changes: 17 additions & 0 deletions testing_utilities/matchers.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#pragma once

#include <nmmintrin.h>

#include <string>

#include "base/status.hpp"
#include "gmock/gmock.h"
#include "google/protobuf/message.h"
#include "google/protobuf/util/message_differencer.h"
#include "quantities/quantities.hpp"
#include "serialization/ksp_plugin.pb.h"

namespace principia {
@@ -37,6 +40,20 @@ MATCHER_P(StatusIs,
return arg.error() == error;
}

MATCHER_P(SSEHighHalfIs,
value,
std::string(negation ? "does not have" : "has") + " high half: " +
::principia::quantities::DebugString(value)) {
return _mm_cvtsd_f64(_mm_unpackhi_pd(arg, arg)) == value;
}

MATCHER_P(SSELowHalfIs,
value,
std::string(negation ? "does not have" : "has") + " low half: " +
::principia::quantities::DebugString(value)) {
return _mm_cvtsd_f64(arg) == value;
}

} // namespace testing_utilities

namespace serialization {