18template <
typename RealType>
30 double sqrt1mroSq = 1;
33 BivariateNormalRand(
double location1,
double location2,
double scale1,
double scale2,
double correlation);
34 [[nodiscard]] std::string
Name()
const override;
37 void SetCovariance(
double scale1,
double scale2,
double correlation);
41 [[nodiscard]]
inline double GetFirstScale() const noexcept {
return sigma1; }
42 [[nodiscard]]
inline double GetSecondScale() const noexcept {
return sigma2; }
48 template <std::uniform_random_bit_generator G>
61template <
typename RealType>
65 SetLocations(location1, location2);
66 SetCovariance(scale1, scale2, correlation);
69template <
typename RealType>
72 return "Bivariate Normal( (" + this->toStringWithPrecision(GetFirstLocation()) +
", " +
73 this->toStringWithPrecision(GetSecondLocation()) +
"), (" + this->toStringWithPrecision(GetFirstScale()) +
74 ", " + this->toStringWithPrecision(GetSecondScale()) +
", " + this->toStringWithPrecision(GetCorrelation()) +
78template <
typename RealType>
83 this->X.SetLocation(mu1);
84 this->Y.SetLocation(mu2);
87template <
typename RealType>
90 if (!(scale1 > 0.0 && scale2 > 0.0))
91 throw std::invalid_argument(
92 "Scales of Bivariate-Normal distribution should be positive, but they're equal to " +
93 std::to_string(scale1) +
" and " + std::to_string(scale2) +
" respectively");
94 if (!(std::fabs(correlation) <= 1.0))
95 throw std::invalid_argument(
96 "Correlation of Bivariate-Normal distribution should be in interval [-1, 1], but it's equal to " +
97 std::to_string(correlation));
102 this->X.SetScale(sigma1);
103 this->Y.SetScale(sigma2);
105 sqrt1mroSq = 0.5 * std::log1pl(-rho * rho);
107 sqrt1mroSq = std::exp(sqrt1mroSq);
110template <
typename RealType>
113 RealType xAdj = (point.first - mu1) / sigma1, yAdj = (point.second - mu2) / sigma2;
115 return (xAdj - yAdj == 0) ? INFINITY : 0.0;
117 return (xAdj + yAdj == 0) ? INFINITY : 0.0;
118 return std::exp(logf(point));
121template <
typename RealType>
125 return this->X.logf(point.first) + this->Y.logf(point.second);
126 RealType xAdj = (point.first - mu1) / sigma1, yAdj = (point.second - mu2) / sigma2;
128 return (xAdj - yAdj == 0) ? INFINITY : -INFINITY;
130 return (xAdj + yAdj == 0) ? INFINITY : -INFINITY;
131 RealType z = xAdj * xAdj - 2 * rho * xAdj * yAdj + yAdj * yAdj;
132 return -(pdfCoef + 0.5 * z / (sqrt1mroSq * sqrt1mroSq));
135template <
typename RealType>
139 return this->X.F(point.first) * this->Y.F(point.second);
143 RealType x = point.first, y = point.second;
144 RealType xAdj = (x - mu1) / sigma1, yAdj = (y - mu2) / sigma2;
146 p1 = (xAdj < yAdj) ? this->X.F(x) : this->Y.F(y);
149 p1 = std::max(this->X.F(x) - standardComplement, 0.0);
151 if (std::fabs(rho) < 1.0) {
152 RealType lowLimit = std::asin(rho);
155 [xAdj, yAdj](
double theta) {
157 RealType cosTheta = std::cos(theta);
158 RealType tanTheta = std::tan(theta);
159 RealType integrand = xAdj * tanTheta - yAdj / cosTheta;
160 integrand *= integrand;
161 integrand += xAdj * xAdj;
162 integrand = std::exp(-0.5 * integrand);
165 lowLimit, highLimit);
170template <
typename RealType>
171template <std::uniform_random_bit_generator G>
176 RealType x = mu1 + sigma1 * Z1;
177 RealType y = mu2 + sigma2 * (rho * Z1 + sqrt1mroSq * Z2);
178 return std::make_pair(x, y);
181template <
typename RealType>
187template <
typename RealType>
190 return std::make_pair(mu1, mu2);
virtual LongDoublePair Mean() const final
Definition bivariate.hpp:50
The BivariateNormalRand class Bivariate Gaussian (normal) distribution.
Definition bivariate_normal.hpp:21
double GetSecondLocation() const noexcept
Definition bivariate_normal.hpp:40
Pair< RealType > operator()(G &g) const
Definition bivariate_normal.hpp:172
double F(const Pair< RealType > &point) const override
Definition bivariate_normal.hpp:136
double GetFirstScale() const noexcept
Definition bivariate_normal.hpp:41
long double Correlation() const override
Definition bivariate_normal.hpp:182
double logf(const Pair< RealType > &point) const override
Definition bivariate_normal.hpp:122
DoublePair GetLocation()
Definition bivariate_normal.hpp:38
double GetFirstLocation() const noexcept
Definition bivariate_normal.hpp:39
double f(const Pair< RealType > &point) const override
Definition bivariate_normal.hpp:111
std::string Name() const override
Definition bivariate_normal.hpp:70
double GetCorrelation() const noexcept
Definition bivariate_normal.hpp:43
double GetSecondScale() const noexcept
Definition bivariate_normal.hpp:42
Pair< RealType > Mode() const override
Definition bivariate_normal.hpp:188
void SetCovariance(double scale1, double scale2, double correlation)
Definition bivariate_normal.hpp:88
BivariateNormalRand(double location1, double location2, double scale1, double scale2, double correlation)
Definition bivariate_normal.hpp:62
void SetLocations(double location1, double location2)
Definition bivariate_normal.hpp:79
The ContinuousBivariateDistribution class Abstract class for all bivariate probability distribution...
Definition continuous_bivariate.hpp:18
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
constexpr long double ln2
Definition constants.hpp:18
constexpr long double half_pi
Definition constants.hpp:23
constexpr long double pi
Definition constants.hpp:22
constexpr long double inv_sqrt2
Definition constants.hpp:28
constexpr long double lnpi
Definition constants.hpp:21
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
int sign(Real x)
Definition functions.hpp:232
Real integrate(const F &f, std::type_identity_t< Real > a, std::type_identity_t< Real > b, std::type_identity_t< Real > tolerance=1e-11, int maxSubdivisions=512)
Global adaptive Gauss-Kronrod quadrature (QUADPACK QAG).
Definition quadrature.hpp:226
Definition bivariate_normal.hpp:10
std::pair< T, T > Pair
Definition fwd.hpp:33
Pair< double > DoublePair
Definition fwd.hpp:39