Skip to content

Commit 9780cbb

Browse files
committed
refactor: use std::expected
1 parent 9ba3c0e commit 9780cbb

7 files changed

Lines changed: 32 additions & 24 deletions

File tree

include/lfmc/numerical_scheme.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ namespace lfmc {
1010
template <typename S, typename P>
1111
concept NumericalScheme =
1212
requires(S const& s, P const& p, double t, double x, double dt, double z) {
13-
{ s.step(p, t, x, dt, z) } -> std::convertible_to<double>;
13+
{ s.step(p, x, t, dt, z) } -> std::convertible_to<double>;
1414
};
1515

1616
template <StochasticProcess P> class EulerMaruyama {
1717
public:
18-
double step(P const& process, double t, double x, double dt, double z) const noexcept {
19-
double drift = process.drift(t, x);
20-
double diffusion = process.diffusion(t, x);
18+
double step(P const& process, double x, double t, double dt, double z) const noexcept {
19+
double drift = process.drift(x, t);
20+
double diffusion = process.diffusion(x, t);
2121
return x + drift * dt + diffusion * std::sqrt(dt) * z;
2222
}
2323
};

include/lfmc/path_generator.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#include "lfmc/stochastic_process.hpp"
55
#include "lfmc/types.hpp"
66

7+
#include <expected>
8+
#include <string>
9+
#include <vector>
10+
711
namespace lfmc {
812

913
template <StochasticProcess Process, typename Scheme>
@@ -17,9 +21,8 @@ class PathGenerator {
1721
PathGenerator(Process process, Scheme scheme)
1822
: process_(std::move(process)), scheme_(std::move(scheme)) {}
1923

20-
// TODO move to cpp file
21-
std::vector<Path> generate_paths(const std::vector<Normals>& normals, size_t steps,
22-
double T) const {
24+
std::expected<std::vector<Path>, std::string>
25+
generate_paths(const std::vector<Normals>& normals, size_t steps, double T) const {
2326
const double dt = T / static_cast<double>(steps);
2427

2528
std::vector<Path> paths;
@@ -31,7 +34,7 @@ class PathGenerator {
3134
path.push_back(x);
3235

3336
for (size_t i = 0; i < steps; ++i) {
34-
x = scheme_.step(process_, t, x, dt, norm[i]);
37+
x = scheme_.step(process_, x, t, dt, norm[i]);
3538
path.push_back(x);
3639
t += dt;
3740
}

include/lfmc/pipeline.hpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,17 @@ template <StochasticProcess SP, NumericalScheme<SP> NS> class Pipeline {
2626

2727
std::expected<double, std::string> run(size_t steps, double T) {
2828
while (!estimator_->converged()) {
29-
// TODO make all the return types std::expected? IDK if it's a good idea for hot loops
30-
// like this but it would make error handling easier and more consistent. For now just
31-
// return
3229
auto normals = random_source_->generate_normals(steps);
33-
if (normals.empty()) {
30+
if (!normals) {
3431
return std::unexpected("Failed to generate random normals");
3532
}
3633

37-
auto paths = path_generator_->generate_paths(normals, steps, T);
38-
if (paths.empty()) {
34+
auto paths = path_generator_->generate_paths(normals.value(), steps, T);
35+
if (!paths) {
3936
return std::unexpected("Failed to generate paths");
4037
}
4138

42-
auto payoffs = payoff_->generate_payoffs(paths);
39+
auto payoffs = payoff_->generate_payoffs(paths.value());
4340
if (!payoffs) {
4441
return std::unexpected("Failed to generate payoffs");
4542
}

include/lfmc/random_source.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "lfmc/types.hpp"
44

5+
#include <expected>
56
#include <random>
67
#include <vector>
78

@@ -10,7 +11,8 @@ namespace lfmc {
1011
class RandomSource {
1112
public:
1213
virtual ~RandomSource() = default;
13-
virtual std::vector<Normals> generate_normals(size_t steps, size_t n = 1) = 0;
14+
virtual std::expected<std::vector<Normals>, std::string> generate_normals(size_t steps,
15+
size_t n = 1) = 0;
1416
};
1517

1618
class PseudoRandomSource : public RandomSource {
@@ -21,7 +23,8 @@ class PseudoRandomSource : public RandomSource {
2123
public:
2224
PseudoRandomSource(unsigned seed = std::random_device{}());
2325

24-
std::vector<Normals> generate_normals(size_t steps, size_t) override;
26+
std::expected<std::vector<Normals>, std::string> generate_normals(size_t steps,
27+
size_t) override;
2528

2629
void seed(unsigned seed);
2730
};
@@ -35,7 +38,8 @@ class AntitheticRandomSource : public RandomSource {
3538
public:
3639
AntitheticRandomSource(unsigned seed = std::random_device{}());
3740

38-
std::vector<Normals> generate_normals(size_t steps, size_t) override;
41+
std::expected<std::vector<Normals>, std::string> generate_normals(size_t steps,
42+
size_t) override;
3943

4044
void seed(unsigned seed);
4145
};

include/lfmc/stochastic_process.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ namespace lfmc {
1313
template <typename P>
1414
concept StochasticProcess = requires(P const& p, double t, double x) {
1515
{ p.initial() } -> std::convertible_to<double>;
16-
{ p.drift(t, x) } -> std::convertible_to<double>;
17-
{ p.diffusion(t, x) } -> std::convertible_to<double>;
16+
{ p.drift(x, t) } -> std::convertible_to<double>;
17+
{ p.diffusion(x, t) } -> std::convertible_to<double>;
1818
};
1919

2020
class GeometricBrownianMotion {
@@ -27,8 +27,8 @@ class GeometricBrownianMotion {
2727
GeometricBrownianMotion(double mu, double sigma, double x0);
2828

2929
double initial() const noexcept;
30-
double drift(double, double x) const noexcept;
31-
double diffusion(double, double x) const noexcept;
30+
double drift(double x, double) const noexcept;
31+
double diffusion(double x, double) const noexcept;
3232

3333
double mu() const noexcept;
3434
double sigma() const noexcept;

src/random_source/antithetic_random_source.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
namespace lfmc {
44
AntitheticRandomSource::AntitheticRandomSource(unsigned seed) : rng_(seed), dist_(0.0, 1.0) {}
55

6-
std::vector<Normals> AntitheticRandomSource::generate_normals(size_t steps, size_t samples) {
6+
std::expected<std::vector<Normals>, std::string>
7+
AntitheticRandomSource::generate_normals(size_t steps, size_t samples) {
78
std::vector<Normals> result(samples, Normals(steps));
89
for (size_t i = 0; i < samples; ++i) {
910
Normals normals(steps);

src/random_source/pseudo_random_source.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#include "lfmc/random_source.hpp"
22
#include "lfmc/types.hpp"
33

4+
#include <expected>
5+
46
namespace lfmc {
57

68
PseudoRandomSource::PseudoRandomSource(unsigned seed) : rng_(seed), dist_(0.0, 1.0) {}
79

8-
std::vector<Normals> PseudoRandomSource::generate_normals(size_t steps, size_t samples) {
10+
std::expected<std::vector<Normals>, std::string>
11+
PseudoRandomSource::generate_normals(size_t steps, size_t samples) {
912
std::vector<Normals> result(samples, Normals(steps));
1013
for (size_t i = 0; i < samples; ++i) {
1114
Normals normals(steps);

0 commit comments

Comments
 (0)