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

Commits on May 27, 2017

  1. Reorder declarations.

    pleroy committed May 27, 2017
    Copy the full SHA
    bd2090c View commit details
  2. Fix the dependencies.

    pleroy committed May 27, 2017
    Copy the full SHA
    2f2898b View commit details
  3. Copy the full SHA
    8fe88d3 View commit details
  4. Remove friendship.

    pleroy committed May 27, 2017
    Copy the full SHA
    79a69c6 View commit details

Commits on May 28, 2017

  1. Merge pull request #1407 from pleroy/QuantitiesCleanup

    Cleanup of quantities
    pleroy authored May 28, 2017
    Copy the full SHA
    e2c4edf View commit details
Showing with 167 additions and 185 deletions.
  1. +1 −0 quantities/bipm.hpp
  2. +1 −0 quantities/constants.hpp
  3. +15 −3 quantities/elementary_functions.hpp
  4. +68 −30 quantities/elementary_functions_body.hpp
  5. +45 −84 quantities/quantities.hpp
  6. +35 −67 quantities/quantities_body.hpp
  7. +1 −1 quantities/si.hpp
  8. +1 −0 quantities/uk.hpp
1 change: 1 addition & 0 deletions quantities/bipm.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#pragma once

#include "quantities/elementary_functions.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/numbers.hpp"
#include "quantities/quantities.hpp"
1 change: 1 addition & 0 deletions quantities/constants.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#pragma once

#include "quantities/elementary_functions.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"
#include "quantities/si.hpp"
18 changes: 15 additions & 3 deletions quantities/elementary_functions.hpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,11 @@ namespace quantities {
// friendships otherwise become impossible to untangle.
namespace internal_quantities {

// Equivalent to |std::abs(x)|.
double Abs(double x);
template<typename D>
Quantity<D> Abs(Quantity<D> const& x);

// We need this for templates, for consistency with the dimensionful Sqrt.
// Equivalent to |std::sqrt(x)|.
double Sqrt(double x);
@@ -19,6 +24,13 @@ double Cbrt(double x);
template<typename D>
CubeRoot<Quantity<D>> Cbrt(Quantity<D> const& x);

// Equivalent to |std::pow(x, exponent)| unless -3 ≤ x ≤ 3, in which case
// explicit specialization yields multiplications statically.
template<int exponent>
constexpr double Pow(double x);
template<int exponent, typename D>
constexpr Exponentiation<Quantity<D>, exponent> Pow(Quantity<D> const& x);

double Sin(Angle const& α);
double Cos(Angle const& α);
double Tan(Angle const& α);
@@ -40,23 +52,23 @@ double Tanh(Angle const& α);
Angle ArcSinh(double x);
Angle ArcCosh(double x);
Angle ArcTanh(double x);

} // namespace internal_quantities

using internal_quantities::Abs;
using internal_quantities::ArcCos;
using internal_quantities::ArcCosh;
using internal_quantities::ArcSin;
using internal_quantities::ArcSinh;
using internal_quantities::ArcTan;
using internal_quantities::ArcTanh;
using internal_quantities::Cbrt;
using internal_quantities::CubeRoot;
using internal_quantities::Cos;
using internal_quantities::Cosh;
using internal_quantities::NthRoot;
using internal_quantities::Pow;
using internal_quantities::Sin;
using internal_quantities::Sinh;
using internal_quantities::Sqrt;
using internal_quantities::SquareRoot;
using internal_quantities::Tan;
using internal_quantities::Tanh;

98 changes: 68 additions & 30 deletions quantities/elementary_functions_body.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

#pragma once

#include "quantities/elementary_functions.hpp"

#include <cmath>
#include <type_traits>

@@ -10,56 +12,92 @@ namespace principia {
namespace quantities {
namespace internal_quantities {

template<int n, typename Q>
struct NthRootGenerator<
n,
Q,
std::enable_if_t<(Q::Dimensions::Length % n) == 0 &&
(Q::Dimensions::Mass % n) == 0 &&
(Q::Dimensions::Time % n) == 0 &&
(Q::Dimensions::Current % n) == 0 &&
(Q::Dimensions::Temperature % n) == 0 &&
(Q::Dimensions::Amount % n) == 0 &&
(Q::Dimensions::LuminousIntensity % n) == 0 &&
(Q::Dimensions::Angle % n) == 0>> {
enum {
Length = Q::Dimensions::Length / n,
Mass = Q::Dimensions::Mass / n,
Time = Q::Dimensions::Time / n,
Current = Q::Dimensions::Current / n,
Temperature = Q::Dimensions::Temperature / n,
Amount = Q::Dimensions::Amount / n,
LuminousIntensity = Q::Dimensions::LuminousIntensity / n,
Angle = Q::Dimensions::Angle / n,
};
using Type = Quantity<Dimensions<Length, Mass, Time, Current, Temperature,
Amount, LuminousIntensity, Angle>>;
};
inline double Abs(double const x) {
return std::abs(x);
}

template<typename D>
FORCE_INLINE Quantity<D> Abs(Quantity<D> const& quantity) {
return SIUnit<Quantity<D>>() * std::abs(quantity / SIUnit<Quantity<D>>());
}

inline double Sqrt(double const x) {
return std::sqrt(x);
}

template<typename D>
inline SquareRoot<Quantity<D>> Sqrt(Quantity<D> const& x) {
return SquareRoot<Quantity<D>>(std::sqrt(x.magnitude_));
SquareRoot<Quantity<D>> Sqrt(Quantity<D> const& x) {
return SIUnit<SquareRoot<Quantity<D>>>() *
std::sqrt(x / SIUnit<Quantity<D>>());
}

inline double Cbrt(double const x) {
return std::cbrt(x);
}

template<typename D>
inline CubeRoot<Quantity<D>> Cbrt(Quantity<D> const& x) {
return CubeRoot<Quantity<D>>(std::cbrt(x.magnitude_));
CubeRoot<Quantity<D>> Cbrt(Quantity<D> const& x) {
return SIUnit<CubeRoot<Quantity<D>>>() * std::cbrt(x / SIUnit<Quantity<D>>());
}

template<int exponent>
constexpr double Pow(double x) {
return std::pow(x, exponent);
}

// Static specializations for frequently-used exponents, so that this gets
// turned into multiplications at compile time.

template<>
inline constexpr double Pow<-3>(double x) {
return 1 / (x * x * x);
}

template<>
inline constexpr double Pow<-2>(double x) {
return 1 / (x * x);
}

template<>
inline constexpr double Pow<-1>(double x) {
return 1 / x;
}

template<>
inline constexpr double Pow<0>(double x) {
return 1;
}

template<>
inline constexpr double Pow<1>(double x) {
return x;
}

template<>
inline constexpr double Pow<2>(double x) {
return x * x;
}

template<>
inline constexpr double Pow<3>(double x) {
return x * x * x;
}

template<int exponent, typename D>
constexpr Exponentiation<Quantity<D>, exponent> Pow(
Quantity<D> const& x) {
return SIUnit<Exponentiation<Quantity<D>, exponent>>() *
Pow<exponent>(x / SIUnit<Quantity<D>>());
}

inline double Sin(Angle const& α) {
return std::sin(α / si::Radian);
}

inline double Cos(Angle const& α) {
return std::cos(α / si::Radian);
}

inline double Tan(Angle const& α) {
return std::tan(α / si::Radian);
}
@@ -75,7 +113,7 @@ inline Angle ArcTan(double const y, double const x) {
}
template<typename D>
Angle ArcTan(Quantity<D> const& y, Quantity<D> const& x) {
return ArcTan(y.magnitude_, x.magnitude_);
return ArcTan(y / SIUnit<Quantity<D>>(), x / SIUnit<Quantity<D>>());
}

inline double Sinh(Angle const& α) {
129 changes: 45 additions & 84 deletions quantities/quantities.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

#pragma once

// We use ostream for logging purposes.
#include <iostream> // NOLINT(readability/streams)
#include <iostream>
#include <limits>
#include <string>
#include <type_traits>
@@ -76,71 +75,6 @@ using SquareRoot = NthRoot<2, Q>;
template<typename Q>
using CubeRoot = NthRoot<3, Q>;

// Returns a positive infinity of |Q|.
template<typename Q>
constexpr Q Infinity();
template<>
constexpr double Infinity<double>();

// Returns a quiet NaN of |Q|.
template<typename Q>
constexpr Q NaN();
template<>
constexpr double NaN<double>();

// Returns the base or derived SI Unit of |Q|.
// For instance, |SIUnit<Action>() == Joule * Second|.
template<typename Q>
constexpr Q SIUnit();
// Returns 1.
template<>
constexpr double SIUnit<double>();

template<typename LDimensions, typename RDimensions>
constexpr Product<Quantity<LDimensions>, Quantity<RDimensions>>
operator*(Quantity<LDimensions> const&, Quantity<RDimensions> const&);
template<typename LDimensions, typename RDimensions>
constexpr Quotient<Quantity<LDimensions>, Quantity<RDimensions>>
operator/(Quantity<LDimensions> const&, Quantity<RDimensions> const&);
template<typename RDimensions>
constexpr Quantity<RDimensions>
operator*(double, Quantity<RDimensions> const&);
template<typename RDimensions>
constexpr typename Quantity<RDimensions>::Inverse
operator/(double, Quantity<RDimensions> const&);

// Equivalent to |std::pow(x, exponent)| unless -3 ≤ x ≤ 3, in which case
// explicit specialization yields multiplications statically.
template<int exponent>
constexpr double Pow(double x);
template<int exponent, typename D>
constexpr Exponentiation<Quantity<D>, exponent> Pow(Quantity<D> const& x);

// Equivalent to |std::abs(x)|.
double Abs(double x);
template<typename D>
Quantity<D> Abs(Quantity<D> const& x);

template<typename D>
SquareRoot<Quantity<D>> Sqrt(Quantity<D> const& x);

template<typename D>
Angle ArcTan(Quantity<D> const& y, Quantity<D> const& x);

template<typename D>
bool IsFinite(Quantity<D> const& x);

std::string DebugString(
double number,
int precision = std::numeric_limits<double>::max_digits10);
template<typename D>
std::string DebugString(
Quantity<D> const& quantity,
int precision = std::numeric_limits<double>::max_digits10);

template<typename D>
std::ostream& operator<<(std::ostream& out, Quantity<D> const& quantity);

template<typename D>
class Quantity final {
public:
@@ -201,25 +135,54 @@ class Quantity final {
friend constexpr Q NaN();
template<typename Q>
friend constexpr Q SIUnit();
};

template<int exponent, typename BaseDimensions>
friend constexpr Exponentiation<Quantity<BaseDimensions>, exponent> Pow(
Quantity<BaseDimensions> const& x);
template<typename LDimensions, typename RDimensions>
constexpr Product<Quantity<LDimensions>, Quantity<RDimensions>>
operator*(Quantity<LDimensions> const&, Quantity<RDimensions> const&);
template<typename LDimensions, typename RDimensions>
constexpr Quotient<Quantity<LDimensions>, Quantity<RDimensions>>
operator/(Quantity<LDimensions> const&, Quantity<RDimensions> const&);
template<typename RDimensions>
constexpr Quantity<RDimensions>
operator*(double, Quantity<RDimensions> const&);
template<typename RDimensions>
constexpr typename Quantity<RDimensions>::Inverse
operator/(double, Quantity<RDimensions> const&);

template<typename E>
friend Quantity<E> Abs(Quantity<E> const&);
// Returns a positive infinity of |Q|.
template<typename Q>
constexpr Q Infinity();
template<>
constexpr double Infinity<double>();

template<typename ArgumentDimensions>
friend SquareRoot<Quantity<ArgumentDimensions>> Sqrt(
Quantity<ArgumentDimensions> const& x);
template<typename ArgumentDimensions>
friend CubeRoot<Quantity<ArgumentDimensions>> Cbrt(
Quantity<ArgumentDimensions> const& x);
template<typename D>
bool IsFinite(Quantity<D> const& x);

friend Angle ArcTan<>(Quantity<D> const& y, Quantity<D> const& x);
friend bool IsFinite<>(Quantity<D> const& x);
friend std::string DebugString<>(Quantity<D> const&, int);
};
// Returns a quiet NaN of |Q|.
template<typename Q>
constexpr Q NaN();
template<>
constexpr double NaN<double>();

// Returns the base or derived SI Unit of |Q|.
// For instance, |SIUnit<Action>() == Joule * Second|.
template<typename Q>
constexpr Q SIUnit();
// Returns 1.
template<>
constexpr double SIUnit<double>();

std::string DebugString(
double number,
int precision = std::numeric_limits<double>::max_digits10);
template<typename D>
std::string DebugString(
Quantity<D> const& quantity,
int precision = std::numeric_limits<double>::max_digits10);

template<typename D>
std::ostream& operator<<(std::ostream& out, Quantity<D> const& quantity);

// A type trait for testing if a type is a quantity.
template<typename T>
@@ -229,7 +192,6 @@ struct is_quantity<Quantity<D>> : std::true_type, not_constructible {};

} // namespace internal_quantities

using internal_quantities::Abs;
using internal_quantities::Amount;
using internal_quantities::Angle;
using internal_quantities::Cube;
@@ -243,7 +205,6 @@ using internal_quantities::Length;
using internal_quantities::LuminousIntensity;
using internal_quantities::Mass;
using internal_quantities::NaN;
using internal_quantities::Pow;
using internal_quantities::Quantity;
using internal_quantities::SIUnit;
using internal_quantities::Square;
102 changes: 35 additions & 67 deletions quantities/quantities_body.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@

#pragma once

#include "quantities/quantities.hpp"

#include <cmath>
#include <cstdio>
#include <limits>
#include <string>

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

namespace principia {
namespace quantities {
@@ -172,6 +173,32 @@ struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent == 1)>>{
using Type = T;
};

template<int n, typename Q>
struct NthRootGenerator<
n,
Q,
std::enable_if_t<(Q::Dimensions::Length % n) == 0 &&
(Q::Dimensions::Mass % n) == 0 &&
(Q::Dimensions::Time % n) == 0 &&
(Q::Dimensions::Current % n) == 0 &&
(Q::Dimensions::Temperature % n) == 0 &&
(Q::Dimensions::Amount % n) == 0 &&
(Q::Dimensions::LuminousIntensity % n) == 0 &&
(Q::Dimensions::Angle % n) == 0>> {
enum {
Length = Q::Dimensions::Length / n,
Mass = Q::Dimensions::Mass / n,
Time = Q::Dimensions::Time / n,
Current = Q::Dimensions::Current / n,
Temperature = Q::Dimensions::Temperature / n,
Amount = Q::Dimensions::Amount / n,
LuminousIntensity = Q::Dimensions::LuminousIntensity / n,
Angle = Q::Dimensions::Angle / n,
};
using Type = Quantity<Dimensions<Length, Mass, Time, Current, Temperature,
Amount, LuminousIntensity, Angle>>;
};

template<typename D>
constexpr Quantity<D>::Quantity() : magnitude_(0) {}

@@ -286,8 +313,7 @@ constexpr Quantity<D> Quantity<D>::operator*(double const right) const {
}

template<typename LDimensions, typename RDimensions>
FORCE_INLINE constexpr Product<Quantity<LDimensions>,
Quantity<RDimensions>>
FORCE_INLINE constexpr Product<Quantity<LDimensions>, Quantity<RDimensions>>
operator*(Quantity<LDimensions> const& left,
Quantity<RDimensions> const& right) {
return Product<Quantity<LDimensions>,
@@ -316,69 +342,6 @@ constexpr typename Quantity<RDimensions>::Inverse operator/(
return typename Quantity<RDimensions>::Inverse(left / right.magnitude_);
}

template<int exponent>
constexpr double Pow(double x) {
return std::pow(x, exponent);
}

// Static specializations for frequently-used exponents, so that this gets
// turned into multiplications at compile time.

template<>
inline constexpr double Pow<-3>(double x) {
return 1 / (x * x * x);
}

template<>
inline constexpr double Pow<-2>(double x) {
return 1 / (x * x);
}

template<>
inline constexpr double Pow<-1>(double x) {
return 1 / x;
}

template<>
inline constexpr double Pow<0>(double x) {
return 1;
}

template<>
inline constexpr double Pow<1>(double x) {
return x;
}

template<>
inline constexpr double Pow<2>(double x) {
return x * x;
}

template<>
inline constexpr double Pow<3>(double x) {
return x * x * x;
}

template<int exponent, typename D>
constexpr Exponentiation<Quantity<D>, exponent> Pow(
Quantity<D> const& x) {
return Exponentiation<Quantity<D>, exponent>(Pow<exponent>(x.magnitude_));
}

inline double Abs(double const x) {
return std::abs(x);
}

template<typename D>
FORCE_INLINE Quantity<D> Abs(Quantity<D> const& quantity) {
return Quantity<D>(std::abs(quantity.magnitude_));
}

template<typename D>
bool IsFinite(Quantity<D> const& x) {
return std::isfinite(x.magnitude_);
}

template<typename Q>
constexpr Q Infinity() {
return Q(std::numeric_limits<double>::infinity());
@@ -389,6 +352,11 @@ constexpr double Infinity<double>() {
return std::numeric_limits<double>::infinity();
}

template<typename D>
bool IsFinite(Quantity<D> const& x) {
return std::isfinite(x / SIUnit<Quantity<D>>());
}

template<typename Q>
constexpr Q NaN() {
return Q(std::numeric_limits<double>::quiet_NaN());
@@ -440,7 +408,7 @@ inline std::string DebugString(double const number, int const precision) {

template<typename D>
std::string DebugString(Quantity<D> const& quantity, int const precision) {
return DebugString(quantity.magnitude_, precision) +
return DebugString(quantity / SIUnit<Quantity<D>>(), precision) +
FormatUnit("m", D::Length) + FormatUnit("kg", D::Mass) +
FormatUnit("s", D::Time) + FormatUnit("A", D::Current) +
FormatUnit("K", D::Temperature) + FormatUnit("mol", D::Amount) +
2 changes: 1 addition & 1 deletion quantities/si.hpp
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ constexpr Angle Degree = π / 180 * Radian;
constexpr Angle ArcMinute = π / 10800 * Radian;
constexpr Angle ArcSecond = π / 648000 * Radian;
constexpr Area Hectare = 1e4 * Metre * Metre;
constexpr Volume Litre = Pow<3>(1e-1 * Metre);
constexpr Volume Litre = 1e-3 * Metre * Metre * Metre;
constexpr Mass Tonne = 1e3 * Kilogram;

// Non-SI units whose values must be obtained experimentally
1 change: 1 addition & 0 deletions quantities/uk.hpp
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
#pragma once

#include "quantities/constants.hpp"
#include "quantities/elementary_functions.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/numbers.hpp"
#include "quantities/quantities.hpp"