Warning, file /include/boost/math/distributions/skew_normal.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_STATS_SKEW_NORMAL_HPP
0008 #define BOOST_STATS_SKEW_NORMAL_HPP
0009
0010
0011
0012
0013
0014
0015
0016 #include <boost/math/distributions/fwd.hpp> // TODO add skew_normal distribution to fwd.hpp!
0017 #include <boost/math/special_functions/owens_t.hpp> // Owen's T function
0018 #include <boost/math/distributions/complement.hpp>
0019 #include <boost/math/distributions/normal.hpp>
0020 #include <boost/math/distributions/detail/common_error_handling.hpp>
0021 #include <boost/math/constants/constants.hpp>
0022 #include <boost/math/tools/tuple.hpp>
0023 #include <boost/math/tools/roots.hpp> // Newton-Raphson
0024 #include <boost/math/tools/assert.hpp>
0025 #include <boost/math/distributions/detail/generic_mode.hpp> // pdf max finder.
0026
0027 #include <utility>
0028 #include <algorithm> // std::lower_bound, std::distance
0029
0030 #ifdef BOOST_MATH_INSTRUMENT_SKEW_NORMAL_ITERATIONS
0031 extern std::uintmax_t global_iter_count;
0032 #endif
0033
0034 namespace boost{ namespace math{
0035
0036 namespace detail
0037 {
0038 template <class RealType, class Policy>
0039 inline bool check_skew_normal_shape(
0040 const char* function,
0041 RealType shape,
0042 RealType* result,
0043 const Policy& pol)
0044 {
0045 if(!(boost::math::isfinite)(shape))
0046 {
0047 *result =
0048 policies::raise_domain_error<RealType>(function,
0049 "Shape parameter is %1%, but must be finite!",
0050 shape, pol);
0051 return false;
0052 }
0053 return true;
0054 }
0055
0056 }
0057
0058 template <class RealType = double, class Policy = policies::policy<> >
0059 class skew_normal_distribution
0060 {
0061 public:
0062 typedef RealType value_type;
0063 typedef Policy policy_type;
0064
0065 skew_normal_distribution(RealType l_location = 0, RealType l_scale = 1, RealType l_shape = 0)
0066 : location_(l_location), scale_(l_scale), shape_(l_shape)
0067 {
0068 static const char* function = "boost::math::skew_normal_distribution<%1%>::skew_normal_distribution";
0069
0070 RealType result;
0071 detail::check_scale(function, l_scale, &result, Policy());
0072 detail::check_location(function, l_location, &result, Policy());
0073 detail::check_skew_normal_shape(function, l_shape, &result, Policy());
0074 }
0075
0076 RealType location()const
0077 {
0078 return location_;
0079 }
0080
0081 RealType scale()const
0082 {
0083 return scale_;
0084 }
0085
0086 RealType shape()const
0087 {
0088 return shape_;
0089 }
0090
0091
0092 private:
0093
0094
0095
0096 RealType location_;
0097 RealType scale_;
0098 RealType shape_;
0099 };
0100
0101 typedef skew_normal_distribution<double> skew_normal;
0102
0103 #ifdef __cpp_deduction_guides
0104 template <class RealType>
0105 skew_normal_distribution(RealType)->skew_normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0106 template <class RealType>
0107 skew_normal_distribution(RealType,RealType)->skew_normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0108 template <class RealType>
0109 skew_normal_distribution(RealType,RealType,RealType)->skew_normal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0110 #endif
0111
0112 template <class RealType, class Policy>
0113 inline const std::pair<RealType, RealType> range(const skew_normal_distribution<RealType, Policy>& )
0114 {
0115 using boost::math::tools::max_value;
0116 return std::pair<RealType, RealType>(
0117 std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(),
0118 std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>());
0119 }
0120
0121 template <class RealType, class Policy>
0122 inline const std::pair<RealType, RealType> support(const skew_normal_distribution<RealType, Policy>& )
0123 {
0124
0125
0126 using boost::math::tools::max_value;
0127 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
0128 }
0129
0130 template <class RealType, class Policy>
0131 inline RealType pdf(const skew_normal_distribution<RealType, Policy>& dist, const RealType& x)
0132 {
0133 const RealType scale = dist.scale();
0134 const RealType location = dist.location();
0135 const RealType shape = dist.shape();
0136
0137 static const char* function = "boost::math::pdf(const skew_normal_distribution<%1%>&, %1%)";
0138
0139 RealType result = 0;
0140 if(false == detail::check_scale(function, scale, &result, Policy()))
0141 {
0142 return result;
0143 }
0144 if(false == detail::check_location(function, location, &result, Policy()))
0145 {
0146 return result;
0147 }
0148 if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
0149 {
0150 return result;
0151 }
0152 if((boost::math::isinf)(x))
0153 {
0154 return 0;
0155 }
0156
0157
0158
0159
0160
0161 if(false == detail::check_x(function, x, &result, Policy()))
0162 {
0163 return result;
0164 }
0165
0166 const RealType transformed_x = (x-location)/scale;
0167
0168 normal_distribution<RealType, Policy> std_normal;
0169
0170 result = pdf(std_normal, transformed_x) * cdf(std_normal, shape*transformed_x) * 2 / scale;
0171
0172 return result;
0173 }
0174
0175 template <class RealType, class Policy>
0176 inline RealType cdf(const skew_normal_distribution<RealType, Policy>& dist, const RealType& x)
0177 {
0178 const RealType scale = dist.scale();
0179 const RealType location = dist.location();
0180 const RealType shape = dist.shape();
0181
0182 static const char* function = "boost::math::cdf(const skew_normal_distribution<%1%>&, %1%)";
0183 RealType result = 0;
0184 if(false == detail::check_scale(function, scale, &result, Policy()))
0185 {
0186 return result;
0187 }
0188 if(false == detail::check_location(function, location, &result, Policy()))
0189 {
0190 return result;
0191 }
0192 if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
0193 {
0194 return result;
0195 }
0196 if((boost::math::isinf)(x))
0197 {
0198 if(x < 0) return 0;
0199 return 1;
0200 }
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 if(false == detail::check_x(function, x, &result, Policy()))
0211 {
0212 return result;
0213 }
0214
0215 const RealType transformed_x = (x-location)/scale;
0216
0217 normal_distribution<RealType, Policy> std_normal;
0218
0219 result = cdf(std_normal, transformed_x) - owens_t(transformed_x, shape)*static_cast<RealType>(2);
0220
0221 return result;
0222 }
0223
0224 template <class RealType, class Policy>
0225 inline RealType cdf(const complemented2_type<skew_normal_distribution<RealType, Policy>, RealType>& c)
0226 {
0227 const RealType scale = c.dist.scale();
0228 const RealType location = c.dist.location();
0229 const RealType shape = c.dist.shape();
0230 const RealType x = c.param;
0231
0232 static const char* function = "boost::math::cdf(const complement(skew_normal_distribution<%1%>&), %1%)";
0233
0234 if((boost::math::isinf)(x))
0235 {
0236 if(x < 0) return 1;
0237 return 0;
0238 }
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248 RealType result = 0;
0249 if(false == detail::check_scale(function, scale, &result, Policy()))
0250 return result;
0251 if(false == detail::check_location(function, location, &result, Policy()))
0252 return result;
0253 if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
0254 return result;
0255 if(false == detail::check_x(function, x, &result, Policy()))
0256 return result;
0257
0258 const RealType transformed_x = (x-location)/scale;
0259
0260 normal_distribution<RealType, Policy> std_normal;
0261
0262 result = cdf(complement(std_normal, transformed_x)) + owens_t(transformed_x, shape)*static_cast<RealType>(2);
0263 return result;
0264 }
0265
0266 template <class RealType, class Policy>
0267 inline RealType location(const skew_normal_distribution<RealType, Policy>& dist)
0268 {
0269 return dist.location();
0270 }
0271
0272 template <class RealType, class Policy>
0273 inline RealType scale(const skew_normal_distribution<RealType, Policy>& dist)
0274 {
0275 return dist.scale();
0276 }
0277
0278 template <class RealType, class Policy>
0279 inline RealType shape(const skew_normal_distribution<RealType, Policy>& dist)
0280 {
0281 return dist.shape();
0282 }
0283
0284 template <class RealType, class Policy>
0285 inline RealType mean(const skew_normal_distribution<RealType, Policy>& dist)
0286 {
0287 BOOST_MATH_STD_USING
0288
0289 using namespace boost::math::constants;
0290
0291
0292
0293
0294
0295 return dist.location() + dist.scale() * dist.shape() / sqrt(pi<RealType>()+pi<RealType>()*dist.shape()*dist.shape()) * root_two<RealType>();
0296 }
0297
0298 template <class RealType, class Policy>
0299 inline RealType variance(const skew_normal_distribution<RealType, Policy>& dist)
0300 {
0301 using namespace boost::math::constants;
0302
0303 const RealType delta2 = dist.shape() != 0 ? static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape())) : static_cast<RealType>(0);
0304
0305
0306 RealType variance = dist.scale()*dist.scale()*(static_cast<RealType>(1)-two_div_pi<RealType>()*delta2);
0307
0308
0309 return variance;
0310 }
0311
0312 namespace detail
0313 {
0314
0315
0316
0317
0318 template <class RealType, class Policy>
0319 inline RealType mode_fallback(const skew_normal_distribution<RealType, Policy>& dist)
0320 {
0321 static const char* function = "mode(skew_normal_distribution<%1%> const&)";
0322 const RealType scale = dist.scale();
0323 const RealType location = dist.location();
0324 const RealType shape = dist.shape();
0325
0326 RealType result;
0327 if(!detail::check_scale(
0328 function,
0329 scale, &result, Policy())
0330 ||
0331 !detail::check_skew_normal_shape(
0332 function,
0333 shape,
0334 &result,
0335 Policy()))
0336 return result;
0337
0338 if( shape == 0 )
0339 {
0340 return location;
0341 }
0342
0343 if( shape < 0 )
0344 {
0345 skew_normal_distribution<RealType, Policy> D(0, 1, -shape);
0346 result = mode_fallback(D);
0347 result = location-scale*result;
0348 return result;
0349 }
0350
0351 BOOST_MATH_STD_USING
0352
0353
0354 static const RealType shapes[] = {
0355 0.0,
0356 1.000000000000000e-004,
0357 2.069138081114790e-004,
0358 4.281332398719396e-004,
0359 8.858667904100824e-004,
0360 1.832980710832436e-003,
0361 3.792690190732250e-003,
0362 7.847599703514606e-003,
0363 1.623776739188722e-002,
0364 3.359818286283781e-002,
0365 6.951927961775606e-002,
0366 1.438449888287663e-001,
0367 2.976351441631319e-001,
0368 6.158482110660261e-001,
0369 1.274274985703135e+000,
0370 2.636650898730361e+000,
0371 5.455594781168514e+000,
0372 1.128837891684688e+001,
0373 2.335721469090121e+001,
0374 4.832930238571753e+001,
0375 1.000000000000000e+002};
0376
0377
0378 static const RealType guess[] = {
0379 0.0,
0380 5.000050000525391e-005,
0381 1.500015000148736e-004,
0382 3.500035000350010e-004,
0383 7.500075000752560e-004,
0384 1.450014500145258e-003,
0385 3.050030500305390e-003,
0386 6.250062500624765e-003,
0387 1.295012950129504e-002,
0388 2.675026750267495e-002,
0389 5.525055250552491e-002,
0390 1.132511325113255e-001,
0391 2.249522495224952e-001,
0392 3.992539925399257e-001,
0393 5.353553535535358e-001,
0394 4.954549545495457e-001,
0395 3.524535245352451e-001,
0396 2.182521825218249e-001,
0397 1.256512565125654e-001,
0398 6.945069450694508e-002,
0399 3.735037350373460e-002
0400 };
0401
0402 const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
0403
0404 typedef typename std::iterator_traits<RealType*>::difference_type diff_type;
0405
0406 const diff_type d = std::distance(shapes, result_ptr);
0407
0408 BOOST_MATH_ASSERT(d > static_cast<diff_type>(0));
0409
0410
0411 if(d < static_cast<diff_type>(21))
0412 {
0413 result = guess[d-static_cast<diff_type>(1)]
0414 + (guess[d]-guess[d-static_cast<diff_type>(1)])/(shapes[d]-shapes[d-static_cast<diff_type>(1)])
0415 * (shape-shapes[d-static_cast<diff_type>(1)]);
0416 }
0417 else
0418 {
0419 result = 1e-4;
0420 }
0421
0422 skew_normal_distribution<RealType, Policy> helper(0, 1, shape);
0423
0424 result = detail::generic_find_mode_01(helper, result, function);
0425
0426 result = result*scale + location;
0427
0428 return result;
0429 }
0430
0431
0432
0433
0434
0435 template <class RealType, class Policy>
0436 struct skew_normal_mode_functor
0437 {
0438 skew_normal_mode_functor(const boost::math::skew_normal_distribution<RealType, Policy> dist)
0439 : distribution(dist)
0440 {
0441 }
0442
0443 boost::math::tuple<RealType, RealType> operator()(RealType const& x)
0444 {
0445 normal_distribution<RealType, Policy> std_normal;
0446 const RealType shape = distribution.shape();
0447 const RealType pdf_x = pdf(distribution, x);
0448 const RealType normpdf_x = pdf(std_normal, x);
0449 const RealType normpdf_ax = pdf(std_normal, x*shape);
0450 RealType fx = static_cast<RealType>(2)*shape*normpdf_ax*normpdf_x - x*pdf_x;
0451 RealType dx = static_cast<RealType>(2)*shape*x*normpdf_x*normpdf_ax*(static_cast<RealType>(1) + shape*shape) + pdf_x + x*fx;
0452
0453 return boost::math::make_tuple(fx, -dx);
0454 }
0455 private:
0456 const boost::math::skew_normal_distribution<RealType, Policy> distribution;
0457 };
0458
0459 }
0460
0461 template <class RealType, class Policy>
0462 inline RealType mode(const skew_normal_distribution<RealType, Policy>& dist)
0463 {
0464 const RealType scale = dist.scale();
0465 const RealType location = dist.location();
0466 const RealType shape = dist.shape();
0467
0468 static const char* function = "boost::math::mode(const skew_normal_distribution<%1%>&, %1%)";
0469
0470 RealType result = 0;
0471 if(false == detail::check_scale(function, scale, &result, Policy()))
0472 return result;
0473 if(false == detail::check_location(function, location, &result, Policy()))
0474 return result;
0475 if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
0476 return result;
0477
0478 if( shape == 0 )
0479 {
0480 return location;
0481 }
0482
0483 if( shape < 0 )
0484 {
0485 skew_normal_distribution<RealType, Policy> D(0, 1, -shape);
0486 result = mode(D);
0487 result = location-scale*result;
0488 return result;
0489 }
0490
0491
0492 static const RealType shapes[] = {
0493 static_cast<RealType>(0.0),
0494 static_cast<RealType>(1.000000000000000e-004),
0495 static_cast<RealType>(2.069138081114790e-004),
0496 static_cast<RealType>(4.281332398719396e-004),
0497 static_cast<RealType>(8.858667904100824e-004),
0498 static_cast<RealType>(1.832980710832436e-003),
0499 static_cast<RealType>(3.792690190732250e-003),
0500 static_cast<RealType>(7.847599703514606e-003),
0501 static_cast<RealType>(1.623776739188722e-002),
0502 static_cast<RealType>(3.359818286283781e-002),
0503 static_cast<RealType>(6.951927961775606e-002),
0504 static_cast<RealType>(1.438449888287663e-001),
0505 static_cast<RealType>(2.976351441631319e-001),
0506 static_cast<RealType>(6.158482110660261e-001),
0507 static_cast<RealType>(1.274274985703135e+000),
0508 static_cast<RealType>(2.636650898730361e+000),
0509 static_cast<RealType>(5.455594781168514e+000),
0510 static_cast<RealType>(1.128837891684688e+001),
0511 static_cast<RealType>(2.335721469090121e+001),
0512 static_cast<RealType>(4.832930238571753e+001),
0513 static_cast<RealType>(1.000000000000000e+002)
0514 };
0515
0516
0517 static const RealType guess[] = {
0518 static_cast<RealType>(0.0),
0519 static_cast<RealType>(5.000050000525391e-005),
0520 static_cast<RealType>(1.500015000148736e-004),
0521 static_cast<RealType>(3.500035000350010e-004),
0522 static_cast<RealType>(7.500075000752560e-004),
0523 static_cast<RealType>(1.450014500145258e-003),
0524 static_cast<RealType>(3.050030500305390e-003),
0525 static_cast<RealType>(6.250062500624765e-003),
0526 static_cast<RealType>(1.295012950129504e-002),
0527 static_cast<RealType>(2.675026750267495e-002),
0528 static_cast<RealType>(5.525055250552491e-002),
0529 static_cast<RealType>(1.132511325113255e-001),
0530 static_cast<RealType>(2.249522495224952e-001),
0531 static_cast<RealType>(3.992539925399257e-001),
0532 static_cast<RealType>(5.353553535535358e-001),
0533 static_cast<RealType>(4.954549545495457e-001),
0534 static_cast<RealType>(3.524535245352451e-001),
0535 static_cast<RealType>(2.182521825218249e-001),
0536 static_cast<RealType>(1.256512565125654e-001),
0537 static_cast<RealType>(6.945069450694508e-002),
0538 static_cast<RealType>(3.735037350373460e-002)
0539 };
0540
0541 const RealType* result_ptr = std::lower_bound(shapes, shapes+21, shape);
0542
0543 typedef typename std::iterator_traits<RealType*>::difference_type diff_type;
0544
0545 const diff_type d = std::distance(shapes, result_ptr);
0546
0547 BOOST_MATH_ASSERT(d > static_cast<diff_type>(0));
0548
0549
0550 RealType search_min = 0;
0551 RealType search_max = 0.55f;
0552
0553
0554 if(d < static_cast<diff_type>(21))
0555 {
0556
0557 result = guess[d-static_cast<diff_type>(1)]
0558 + (guess[d]-guess[d-static_cast<diff_type>(1)])/(shapes[d]-shapes[d-static_cast<diff_type>(1)])
0559 * (shape-shapes[d-static_cast<diff_type>(1)]);
0560 }
0561 else
0562 {
0563 result = 1e-4f;
0564 search_max = guess[19];
0565 }
0566
0567 const int get_digits = policies::digits<RealType, Policy>();
0568 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0569
0570 skew_normal_distribution<RealType, Policy> helper(0, 1, shape);
0571
0572 result = tools::newton_raphson_iterate(detail::skew_normal_mode_functor<RealType, Policy>(helper), result,
0573 search_min, search_max, get_digits, max_iter);
0574 if (max_iter >= policies::get_max_root_iterations<Policy>())
0575 {
0576 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
0577 " either there is no answer to quantile or the answer is infinite. Current best guess is %1%", result, Policy());
0578 }
0579
0580 result = result*scale + location;
0581
0582 return result;
0583 }
0584
0585
0586
0587 template <class RealType, class Policy>
0588 inline RealType skewness(const skew_normal_distribution<RealType, Policy>& dist)
0589 {
0590 BOOST_MATH_STD_USING
0591 using namespace boost::math::constants;
0592
0593 static const RealType factor = four_minus_pi<RealType>()/static_cast<RealType>(2);
0594 const RealType delta = dist.shape() / sqrt(static_cast<RealType>(1)+dist.shape()*dist.shape());
0595
0596 return static_cast<RealType>(factor * pow(root_two_div_pi<RealType>() * delta, 3) /
0597 pow(static_cast<RealType>(1)-two_div_pi<RealType>()*delta*delta, static_cast<RealType>(1.5)));
0598 }
0599
0600 template <class RealType, class Policy>
0601 inline RealType kurtosis(const skew_normal_distribution<RealType, Policy>& dist)
0602 {
0603 return kurtosis_excess(dist)+static_cast<RealType>(3);
0604 }
0605
0606 template <class RealType, class Policy>
0607 inline RealType kurtosis_excess(const skew_normal_distribution<RealType, Policy>& dist)
0608 {
0609 using namespace boost::math::constants;
0610
0611 static const RealType factor = pi_minus_three<RealType>()*static_cast<RealType>(2);
0612
0613 const RealType delta2 = dist.shape() != 0 ? static_cast<RealType>(1) / (static_cast<RealType>(1)+static_cast<RealType>(1)/(dist.shape()*dist.shape())) : static_cast<RealType>(0);
0614
0615 const RealType x = static_cast<RealType>(1)-two_div_pi<RealType>()*delta2;
0616 const RealType y = two_div_pi<RealType>() * delta2;
0617
0618 return factor * y*y / (x*x);
0619 }
0620
0621 template <class RealType, class Policy>
0622 inline RealType quantile(const skew_normal_distribution<RealType, Policy>& dist, const RealType& p)
0623 {
0624 const RealType scale = dist.scale();
0625 const RealType location = dist.location();
0626 const RealType shape = dist.shape();
0627
0628 static const char* function = "boost::math::quantile(const skew_normal_distribution<%1%>&, %1%)";
0629
0630 RealType result = 0;
0631 if(false == detail::check_scale(function, scale, &result, Policy()))
0632 return result;
0633 if(false == detail::check_location(function, location, &result, Policy()))
0634 return result;
0635 if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
0636 return result;
0637 if(false == detail::check_probability(function, p, &result, Policy()))
0638 return result;
0639
0640
0641 RealType x = -boost::math::erfc_inv(2 * p, Policy()) * constants::root_two<RealType>();
0642
0643
0644 if(shape != 0)
0645 {
0646 const RealType skew = skewness(dist);
0647 const RealType exk = kurtosis_excess(dist);
0648
0649 x = x + (x*x-static_cast<RealType>(1))*skew/static_cast<RealType>(6)
0650 + x*(x*x-static_cast<RealType>(3))*exk/static_cast<RealType>(24)
0651 - x*(static_cast<RealType>(2)*x*x-static_cast<RealType>(5))*skew*skew/static_cast<RealType>(36);
0652 }
0653
0654 result = standard_deviation(dist)*x+mean(dist);
0655
0656
0657 if(shape == 0)
0658 return result;
0659
0660
0661
0662 const int get_digits = policies::digits<RealType, Policy>();
0663 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0664
0665 if (result == 0)
0666 result = tools::min_value<RealType>();
0667
0668 auto fun = [&, dist, p](const RealType& x)->RealType { return cdf(dist, x) - p; };
0669
0670 RealType f_result = fun(result);
0671
0672 if (f_result == 0)
0673 return result;
0674
0675 if (f_result * result > 0)
0676 {
0677
0678 RealType f_zero = fun(static_cast<RealType>(0));
0679 if (f_zero * f_result > 0)
0680 {
0681
0682 result = -result;
0683 f_result = fun(result);
0684 }
0685 }
0686
0687 RealType scaling_factor = 1.25;
0688 if (f_result * result > 0)
0689 {
0690
0691 scaling_factor = 16;
0692 }
0693
0694 auto p_result = tools::bracket_and_solve_root(fun, result, scaling_factor, true, tools::eps_tolerance<RealType>(get_digits), max_iter, Policy());
0695
0696 #ifdef BOOST_MATH_INSTRUMENT_SKEW_NORMAL_ITERATIONS
0697 global_iter_count += max_iter;
0698 #endif
0699
0700 result = (p_result.first + p_result.second) / 2;
0701
0702
0703
0704
0705 RealType step = fun(result) / pdf(dist, result);
0706
0707 if (result - step <= p_result.first)
0708 result = p_result.first;
0709 else if (result - step >= p_result.second)
0710 result = p_result.second;
0711 else
0712 result -= step;
0713
0714 if (max_iter >= policies::get_max_root_iterations<Policy>())
0715 {
0716 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time: either there is no answer to quantile"
0717 " or the answer is infinite. Current best guess is %1%", result, Policy());
0718 }
0719
0720 return result;
0721 }
0722
0723 template <class RealType, class Policy>
0724 inline RealType quantile(const complemented2_type<skew_normal_distribution<RealType, Policy>, RealType>& c)
0725 {
0726 const RealType scale = c.dist.scale();
0727 const RealType location = c.dist.location();
0728 const RealType shape = c.dist.shape();
0729
0730 static const char* function = "boost::math::quantile(const complement(skew_normal_distribution<%1%>&), %1%)";
0731 RealType result = 0;
0732 if(false == detail::check_scale(function, scale, &result, Policy()))
0733 return result;
0734 if(false == detail::check_location(function, location, &result, Policy()))
0735 return result;
0736 if(false == detail::check_skew_normal_shape(function, shape, &result, Policy()))
0737 return result;
0738 RealType q = c.param;
0739 if(false == detail::check_probability(function, q, &result, Policy()))
0740 return result;
0741
0742 skew_normal_distribution<RealType, Policy> D(-location, scale, -shape);
0743
0744 result = -quantile(D, q);
0745
0746 return result;
0747 }
0748
0749
0750 }
0751 }
0752
0753
0754
0755
0756 #include <boost/math/distributions/detail/derived_accessors.hpp>
0757
0758 #endif
0759
0760