32 #ifndef VSMC_RNG_STABLE_DISTRIBUTION_HPP
33 #define VSMC_RNG_STABLE_DISTRIBUTION_HPP
37 #define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_STABILITY(a) \
38 VSMC_RUNTIME_ASSERT((a > 0 && a <= 2), \
39 ("**StableDistribution** CONSTRUCTED WITH INVALID " \
40 "STABILITY PARAMETER VALUE"))
42 #define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SKEWNESS(a) \
43 VSMC_RUNTIME_ASSERT((a >= -1 && a <= 1), \
44 ("**StableDistribution** CONSTRUCTED WITH INVALID " \
45 "SKEWNESS PARAMETER VALUE"))
47 #define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SCALE(a) \
48 VSMC_RUNTIME_ASSERT((a > 0), \
49 ("**StableDistribution** CONSTRUCTED WITH INVALID " \
50 "SCALE PARAMETER VALUE"))
56 template <
typename FPType>
78 result_type
skewness ()
const {
return skewness_;}
79 result_type
location ()
const {
return location_;}
80 result_type
scale ()
const {
return scale_;}
85 if (param1.stability_ < param2.stability_ ||
86 param1.stability_ > param2.stability_)
88 if (param1.skewness_ < param2.skewness_ ||
89 param1.skewness_ > param2.skewness_)
91 if (param1.location_ < param2.location_ ||
92 param1.location_ > param2.location_)
94 if (param1.scale_ < param2.scale_ ||
95 param1.scale_ > param2.scale_)
102 {
return !(param1 == param2);}
104 template <
typename CharT,
typename Traits>
105 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
111 os << param.stability_ <<
' ' << param.skewness_ <<
' ';
112 os << param.location_ <<
' ' << param.scale_ <<
' ';
117 template <
typename CharT,
typename Traits>
118 friend inline std::basic_istream<CharT, Traits> &
operator>> (
127 result_type
scale = 0;
131 is >> std::ws >>
scale;
134 if (stability > 0 && stability <= 2 &&
135 skewness >= -1 && skewness <= 1 && scale > 0) {
139 param.scale_ =
scale;
141 is.setstate(std::ios_base::failbit);
150 result_type stability_;
151 result_type skewness_;
152 result_type location_;
161 zeta_(0), xi_(0), stability_1_(false)
175 zeta_(0), xi_(0), stability_1_(false)
187 {
return param_type(stability_, skewness_, location_, scale_);}
194 scale_ = param.
scale();
203 result_type
scale ()
const {
return scale_;}
205 {
return -std::numeric_limits<result_type>::infinity();}
207 {
return std::numeric_limits<result_type>::infinity();}
209 template <
typename Eng>
213 return trans_1(standard_1(eng));
215 return trans_a(standard_a(eng));
222 if (rstable1.stability_ < rstable2.stability_ ||
223 rstable1.stability_ > rstable2.stability_)
225 if (rstable1.skewness_ < rstable2.skewness_ ||
226 rstable1.skewness_ > rstable2.skewness_)
228 if (rstable1.location_ < rstable2.location_ ||
229 rstable1.location_ > rstable2.location_)
231 if (rstable1.scale_ < rstable2.scale_ ||
232 rstable1.scale_ > rstable2.scale_)
240 {
return !(rstable1 == rstable2);}
242 template <
typename CharT,
typename Traits>
243 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
244 std::basic_ostream<CharT, Traits> &os,
250 os << rstable.stability_ <<
' ' << rstable.skewness_ <<
' ';
251 os << rstable.location_ <<
' ' << rstable.scale_ <<
' ';
256 template <
typename CharT,
typename Traits>
257 friend inline std::basic_istream<CharT, Traits> &
operator>> (
258 std::basic_istream<CharT, Traits> &is,
267 result_type
scale = 0;
271 is >> std::ws >>
scale;
274 if (stability > 0 && stability <= 2 &&
275 skewness >= -1 && skewness <= 1 && scale > 0) {
279 rstable.scale_ =
scale;
281 is.setstate(std::ios_base::failbit);
290 result_type stability_;
291 result_type skewness_;
292 result_type location_;
298 template <
typename Eng>
299 result_type standard_1 (Eng &eng)
const
305 cxx11::uniform_real_distribution<result_type> runif(0, 1);
306 result_type w = -log(runif(eng));
307 result_type u = (runif(eng) - 0.5) * math::pi<result_type>();
308 result_type a = (math::pi_by2<result_type>() + skewness_ * u) * tan(u);
309 result_type b = log(math::pi_by2<result_type>() * w * cos(u));
310 result_type c = log(math::pi_by2<result_type>() + skewness_ * u);
311 result_type x = (a - skewness_ * (b - c)) / xi_;
316 template <
typename Eng>
317 result_type standard_a (Eng &eng)
const
324 cxx11::uniform_real_distribution<result_type> runif(0, 1);
325 result_type w = -log(runif(eng));
326 result_type u = (runif(eng) - 0.5) * math::pi<result_type>();
327 result_type a = 0.5 * log(1 + zeta_ * zeta_) / stability_;
328 result_type b = sin(stability_ * (u + xi_));
329 result_type c = log(cos(u)) / stability_;
330 result_type d = (1 - stability_) / stability_ * log(
331 cos(u - stability_ * (u + xi_)) / w);
332 result_type x = b * std::exp(a - c + d);
337 result_type trans_1 (result_type x)
const
341 return scale_ * x + location_ +
342 2 * math::pi_inv<result_type>() * skewness_ * scale_ * log(scale_);
345 result_type trans_a (result_type x)
const
346 {
return scale_ * x + location_;}
353 if (stability_ < 1 || stability_ > 1) {
354 stability_1_ =
false;
355 zeta_ = -skewness_ * tan(math::pi_by2<result_type>() * stability_);
356 xi_ = 1 / stability_ * atan(-zeta_);
359 zeta_ = -std::numeric_limits<result_type>::infinity();
360 xi_ = math::pi_by2<result_type>();
367 #endif // VSMC_RNG_STABLE_DISTRIBUTION_HPP
param_type(result_type stability=1, result_type skewness=0, result_type location=0, result_type scale=1)
StableDistribution< FPType > distribution_type
result_type scale() const
result_type skewness() const
StableDistribution(const param_type ¶m)
#define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SKEWNESS(a)
friend bool operator!=(const StableDistribution< FPType > &rstable1, const StableDistribution< FPType > &rstable2)
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, StableDistribution< FPType > &rstable)
#define VSMC_MNE
Avoid MSVC stupid behavior: MNE = Macro No Expansion.
result_type skewness() const
friend bool operator==(const param_type ¶m1, const param_type ¶m2)
friend bool operator==(const StableDistribution< FPType > &rstable1, const StableDistribution< FPType > &rstable2)
void param(const param_type ¶m)
StableDistribution(result_type stability=1, result_type skewness=0, result_type location=0, result_type scale=1)
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const param_type ¶m)
#define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SCALE(a)
friend bool operator!=(const param_type param1, const param_type param2)
result_type operator()(Eng &eng) const
result_type stability() const
result_type location() const
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const StableDistribution< FPType > &rstable)
result_type stability() const
#define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_STABILITY(a)
result_type location() const
result_type scale() const
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, param_type ¶m)