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

Commits on Jul 2, 2020

  1. The Dirichlet function, and major changes to Poisson series and polyn…

    …omials to make them work on Instant.
    pleroy committed Jul 2, 2020
    Copy the full SHA
    708187e View commit details
  2. Copy the full SHA
    94baf42 View commit details
  3. Use gmock.

    pleroy committed Jul 2, 2020
    Copy the full SHA
    d3021e6 View commit details
  4. Lint and tolerances.

    pleroy committed Jul 2, 2020
    Copy the full SHA
    912df88 View commit details

Commits on Jul 3, 2020

  1. Merge pull request #2624 from pleroy/Windows

    Change Poisson series to take Instant, not Time
    pleroy authored Jul 3, 2020
    Copy the full SHA
    3538679 View commit details
26 changes: 26 additions & 0 deletions numerics/apodization.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

#pragma once

#include "geometry/named_quantities.hpp"
#include "numerics/poisson_series.hpp"

namespace principia {
namespace numerics {
namespace apodization {
namespace internal_apodization {

using geometry::Instant;

template<template<typename, typename, int> class Evaluator>
PoissonSeries<double, 0, Evaluator> Dirichlet(Instant const& t_min,
Instant const& t_max);

} // namespace internal_apodization

using internal_apodization::Dirichlet;

} // namespace apodization
} // namespace numerics
} // namespace principia

#include "numerics/apodization_body.hpp"
26 changes: 26 additions & 0 deletions numerics/apodization_body.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

#pragma once

#include "numerics/apodization.hpp"

#include "geometry/barycentre_calculator.hpp"

namespace principia {
namespace numerics {
namespace apodization {
namespace internal_apodization {

using geometry::Barycentre;

template<template<typename, typename, int> class Evaluator>
PoissonSeries<double, 0, Evaluator> Dirichlet(Instant const& t_min,
Instant const& t_max) {
using Result = PoissonSeries<double, 0, Evaluator>;
auto const midpoint = Barycentre<Instant, double>({t_min, t_max}, {0.5, 0.5});
return Result(typename Result::Polynomial({1}, midpoint), {});
}

} // namespace internal_apodization
} // namespace apodization
} // namespace numerics
} // namespace principia
35 changes: 35 additions & 0 deletions numerics/apodization_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

#include "numerics/apodization.hpp"

#include "geometry/named_quantities.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "numerics/polynomial_evaluators.hpp"
#include "quantities/si.hpp"
#include "testing_utilities/almost_equals.hpp"

namespace principia {
namespace numerics {

using geometry::Instant;
using quantities::si::Second;
using testing_utilities::AlmostEquals;

class ApodizationTest : public ::testing::Test {
protected:
ApodizationTest() : t1_(t0_ - 1 * Second), t2_(t0_ + 2 * Second) {}

Instant const t0_;
Instant const t1_;
Instant const t2_;
};

TEST_F(ApodizationTest, Dirichlet) {
auto a = apodization::Dirichlet<HornerEvaluator>(t1_, t2_);
EXPECT_THAT(1, AlmostEquals(a.Evaluate(t0_), 0));
EXPECT_THAT(1, AlmostEquals(a.Evaluate(t0_ + 0.5 * Second), 0));
EXPECT_THAT(1, AlmostEquals(a.Evaluate(t0_ + 1 * Second), 0));
}

} // namespace numerics
} // namespace principia
3 changes: 3 additions & 0 deletions numerics/numerics.vcxproj
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
<Import Project="..\third_party_zfp.props" />
</ImportGroup>
<ItemGroup>
<ClInclude Include="apodization_body.hpp" />
<ClInclude Include="combinatorics.hpp" />
<ClInclude Include="combinatorics_body.hpp" />
<ClInclude Include="cbrt.hpp" />
@@ -51,10 +52,12 @@
<ClInclude Include="root_finders_body.hpp" />
<ClInclude Include="ulp_distance.hpp" />
<ClInclude Include="ulp_distance_body.hpp" />
<ClInclude Include="apodization.hpp" />
<ClInclude Include="чебышёв_series.hpp" />
<ClInclude Include="чебышёв_series_body.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="apodization_test.cpp" />
<ClCompile Include="cbrt.cpp" />
<ClCompile Include="cbrt_test.cpp" />
<ClCompile Include="combinatorics_test.cpp" />
9 changes: 9 additions & 0 deletions numerics/numerics.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -131,6 +131,12 @@
<ClInclude Include="poisson_series_body.hpp">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="apodization.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="apodization_body.hpp">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="чебышёв_series_test.cpp">
@@ -202,6 +208,9 @@
<ClCompile Include="poisson_series_test.cpp">
<Filter>Test Files</Filter>
</ClCompile>
<ClCompile Include="apodization_test.cpp">
<Filter>Test Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="xgscd.proto.txt">
7 changes: 5 additions & 2 deletions numerics/poisson_series.hpp
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
#include <algorithm>
#include <map>

#include "geometry/named_quantities.hpp"
#include "numerics/polynomial.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"
@@ -12,6 +13,7 @@ namespace principia {
namespace numerics {
namespace internal_poisson_series {

using geometry::Instant;
using quantities::AngularFrequency;
using quantities::Product;
using quantities::Quotient;
@@ -27,7 +29,7 @@ template<typename Value, int degree_,
class PoissonSeries {
public:
using Polynomial =
numerics::PolynomialInMonomialBasis<Value, Time, degree_, Evaluator>;
numerics::PolynomialInMonomialBasis<Value, Instant, degree_, Evaluator>;

// TODO(phl): Use designated initializers for this struct once this project
// can be compiled using c++latest.
@@ -41,13 +43,14 @@ class PoissonSeries {
PoissonSeries(Polynomial const& aperiodic,
PolynomialsByAngularFrequency const& periodic);

Value Evaluate(Time const& t) const;
Value Evaluate(Instant const& t) const;

// The constant term of the result is zero.
PoissonSeries<quantities::Primitive<Value, Time>, degree_ + 1, Evaluator>
Primitive() const;

private:
Instant origin_; // Common to all polynomials.
Polynomial aperiodic_;
// All the keys in this map are positive.
PolynomialsByAngularFrequency periodic_;
43 changes: 27 additions & 16 deletions numerics/poisson_series_body.hpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
#include <optional>

#include "quantities/elementary_functions.hpp"
#include "quantities/si.hpp"

namespace principia {
namespace numerics {
@@ -18,12 +19,12 @@ using quantities::Cos;
using quantities::Infinity;
using quantities::Primitive;
using quantities::Sin;
using quantities::si::Radian;

template<typename Value, int degree_,
template<typename, typename, int> class Evaluator>
typename PoissonSeries<Primitive<Value, Time>,
degree_ + 1,
Evaluator>::Polynomials
typename PoissonSeries<Primitive<Value, Time>, degree_ + 1, Evaluator>::
Polynomials
AngularFrequencyPrimitive(
AngularFrequency const& ω,
typename PoissonSeries<Value, degree_, Evaluator>::Polynomials const&
@@ -33,13 +34,15 @@ AngularFrequencyPrimitive(

// Integration by parts.
typename Result::Polynomials const first_part{
/*sin=*/Result::Polynomial(polynomials.cos / ω * Radian),
/*cos=*/Result::Polynomial(-polynomials.sin / ω * Radian)};
/*sin=*/typename Result::Polynomial(polynomials.cos / ω * Radian),
/*cos=*/typename Result::Polynomial(-polynomials.sin / ω * Radian)};
if constexpr (degree_ == 0) {
return first_part;
} else {
auto const sin_polynomial = -polynomials.cos.Derivative<1>() / ω * Radian;
auto const cos_polynomial = polynomials.sin.Derivative<1>() / ω * Radian;
auto const sin_polynomial =
-polynomials.cos.template Derivative<1>() / ω * Radian;
auto const cos_polynomial =
polynomials.sin.template Derivative<1>() / ω * Radian;
auto const second_part =
AngularFrequencyPrimitive<Value, degree_ - 1, Evaluator>(
ω,
@@ -55,37 +58,45 @@ template<typename Value, int degree_,
PoissonSeries<Value, degree_, Evaluator>::PoissonSeries(
Polynomial const& aperiodic,
PolynomialsByAngularFrequency const& periodic)
: aperiodic_(aperiodic) {
: origin_(aperiodic.origin()),
aperiodic_(aperiodic) {
// The |periodic| map may have elements with positive or negative angular
// frequencies. Normalize our member variable to only have positive angular
// frequencies.
for (auto it = periodic.crbegin(); it != periodic.crend(); ++it) {
auto const ω = it->first;
auto const polynomials = it->second;

// All polynomials must have the same origin.
CHECK_EQ(origin_, polynomials.sin.origin());
CHECK_EQ(origin_, polynomials.cos.origin());

if (ω < AngularFrequency{}) {
auto const positive_it = periodic_.find(-ω);
if (positive_it == periodic_.cend()) {
periodic_.emplace(-ω,
Polynomials{/*sin=*/-it->second.sin,
/*cos=*/it->second.cos});
Polynomials{/*sin=*/-polynomials.sin,
/*cos=*/polynomials.cos});
} else {
positive_it->second.sin -= it->second.sin;
positive_it->second.cos += it->second.cos;
positive_it->second.sin -= polynomials.sin;
positive_it->second.cos += polynomials.cos;
}
} else if (ω > AngularFrequency{}) {
periodic_.insert(periodic_.cbegin(), *it);
} else {
aperiodic_ += it->second.cos;
aperiodic_ += polynomials.cos;
}
}
}

template<typename Value, int degree_,
template<typename, typename, int> class Evaluator>
Value PoissonSeries<Value, degree_, Evaluator>::Evaluate(Time const& t) const {
Value PoissonSeries<Value, degree_, Evaluator>::Evaluate(
Instant const& t) const {
Value result = aperiodic_.Evaluate(t);
for (auto const& [ω, polynomials] : periodic_) {
result += polynomials.sin.Evaluate(t) * Sin(ω * t) +
polynomials.cos.Evaluate(t) * Cos(ω * t);
result += polynomials.sin.Evaluate(t) * Sin(ω * (t - origin_)) +
polynomials.cos.Evaluate(t) * Cos(ω * (t - origin_));
}
return result;
}
Loading