Program Listing for File PDFReflect.hpp
↰ Return to documentation for file (src/pdfs/PDFReflect.hpp)
#ifndef PDFREFLECT_HPP
#define PDFREFLECT_HPP
#include "PDF.hpp"
#include <functional>
#include <limits>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
namespace pdfs {
class PDFReflect : public PDF {
public:
// Un-hide PDF::integral()'s no-argument overload: declaring
// integral(a, b) below would otherwise hide every base-class
// overload of the name "integral" in this class's scope, per
// ordinary C++ name-hiding rules, even though the no-argument
// form needs no change (see integral(a,b)'s own comment).
using PDF::integral;
[[nodiscard]] auto toToml() const -> std::string override
{
throw std::logic_error("PDFReflect::toToml: a reflected view of a PDF "
"cannot be serialized; serialize the PDF it wraps instead");
}
explicit PDFReflect(const PDF& pdf) :
PDFReflect(pdf, 0.5 * (pdf.getMin() + pdf.getMax()))
{ }
PDFReflect(const PDF& pdf, const double pivot) :
pdf_(std::cref(pdf)),
pivot_(pivot)
{
sMin_ = pdf.getMin();
sMax_ = pdf.getMax();
wgt_ = pdf.getWeights();
}
auto operator()(double x) const -> double override
{
return pdf_.get()(reflect(x));
}
[[nodiscard]] auto expectationValue() const -> double override
{
return reflect(pdf_.get().expectationValue());
}
[[nodiscard]] auto deltas() const -> std::vector<std::pair<double, double>> override
{
auto result = pdf_.get().deltas();
for (auto& [x, w] : result) { x = reflect(x); }
return result;
}
[[nodiscard]] auto expectationValue(const double a, const double b) const -> double override
{
const double aReflect = reflect(b);
const double bReflect = reflect(a);
return reflect(pdf_.get().expectationValue(aReflect, bReflect));
}
[[nodiscard]] auto integral(const double a, const double b) const -> double override
{
const double aReflect = reflect(b);
const double bReflect = reflect(a);
return pdf_.get().integral(aReflect, bReflect);
}
[[nodiscard]]
auto draw(const double a = std::numeric_limits<double>::lowest(),
const double b = std::numeric_limits<double>::max()) const -> double override
{
const double aReflect = reflect(b);
const double bReflect = reflect(a);
return reflect(pdf_.get().draw(aReflect, bReflect));
}
[[nodiscard]] auto draw(unsigned int nDraw,
double a = std::numeric_limits<double>::lowest(),
double b = std::numeric_limits<double>::max())
const -> std::vector<double> override
{
const double aReflect = reflect(b);
const double bReflect = reflect(a);
auto result = pdf_.get().draw(nDraw, aReflect, bReflect);
for (auto& r : result) { r = reflect(r); }
return result;
}
[[nodiscard]] auto drawTarget(double target,
double a = std::numeric_limits<double>::lowest(),
double b = std::numeric_limits<double>::max()) const
-> std::vector<double> override
{
const double aReflect = reflect(b);
const double bReflect = reflect(a);
auto result = pdf_.get().drawTarget(target, aReflect, bReflect);
for (auto& r : result) { r = reflect(r); }
return result;
}
private:
[[nodiscard]] auto reflect(const double x) const -> double
{
return (2.0 * pivot_) - x;
}
std::reference_wrapper<const PDF> pdf_;
double pivot_;
};
} // namespace pdfs
#endif // PDFREFLECT_HPP