File indexing completed on 2025-09-18 08:48:59
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_SF_ERF_INV_HPP
0008 #define BOOST_MATH_SF_ERF_INV_HPP
0009
0010 #ifdef _MSC_VER
0011 #pragma once
0012 #pragma warning(push)
0013 #pragma warning(disable:4127)
0014 #pragma warning(disable:4702)
0015 #endif
0016
0017 #include <boost/math/tools/config.hpp>
0018
0019 #ifndef BOOST_MATH_HAS_NVRTC
0020
0021 #include <type_traits>
0022
0023 namespace boost{ namespace math{
0024
0025 namespace detail{
0026
0027
0028
0029
0030 template <class T, class Policy>
0031 BOOST_MATH_GPU_ENABLED T erf_inv_imp(const T& p, const T& q, const Policy&, const std::integral_constant<int, 64>&)
0032 {
0033 BOOST_MATH_STD_USING
0034
0035 T result = 0;
0036
0037 if(p <= 0.5)
0038 {
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 0.0891314744949340820313f;
0053 BOOST_MATH_STATIC const T P[] = {
0054 BOOST_MATH_BIG_CONSTANT(T, 64, -0.000508781949658280665617),
0055 BOOST_MATH_BIG_CONSTANT(T, 64, -0.00836874819741736770379),
0056 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0334806625409744615033),
0057 BOOST_MATH_BIG_CONSTANT(T, 64, -0.0126926147662974029034),
0058 BOOST_MATH_BIG_CONSTANT(T, 64, -0.0365637971411762664006),
0059 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0219878681111168899165),
0060 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00822687874676915743155),
0061 BOOST_MATH_BIG_CONSTANT(T, 64, -0.00538772965071242932965)
0062 };
0063 BOOST_MATH_STATIC const T Q[] = {
0064 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0065 BOOST_MATH_BIG_CONSTANT(T, 64, -0.970005043303290640362),
0066 BOOST_MATH_BIG_CONSTANT(T, 64, -1.56574558234175846809),
0067 BOOST_MATH_BIG_CONSTANT(T, 64, 1.56221558398423026363),
0068 BOOST_MATH_BIG_CONSTANT(T, 64, 0.662328840472002992063),
0069 BOOST_MATH_BIG_CONSTANT(T, 64, -0.71228902341542847553),
0070 BOOST_MATH_BIG_CONSTANT(T, 64, -0.0527396382340099713954),
0071 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0795283687341571680018),
0072 BOOST_MATH_BIG_CONSTANT(T, 64, -0.00233393759374190016776),
0073 BOOST_MATH_BIG_CONSTANT(T, 64, 0.000886216390456424707504)
0074 };
0075
0076 T g = p * (p + 10);
0077 T r = tools::evaluate_polynomial(P, p) / tools::evaluate_polynomial(Q, p);
0078 result = g * Y + g * r;
0079 }
0080 else if(q >= 0.25)
0081 {
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 2.249481201171875f;
0096 BOOST_MATH_STATIC const T P[] = {
0097 BOOST_MATH_BIG_CONSTANT(T, 64, -0.202433508355938759655),
0098 BOOST_MATH_BIG_CONSTANT(T, 64, 0.105264680699391713268),
0099 BOOST_MATH_BIG_CONSTANT(T, 64, 8.37050328343119927838),
0100 BOOST_MATH_BIG_CONSTANT(T, 64, 17.6447298408374015486),
0101 BOOST_MATH_BIG_CONSTANT(T, 64, -18.8510648058714251895),
0102 BOOST_MATH_BIG_CONSTANT(T, 64, -44.6382324441786960818),
0103 BOOST_MATH_BIG_CONSTANT(T, 64, 17.445385985570866523),
0104 BOOST_MATH_BIG_CONSTANT(T, 64, 21.1294655448340526258),
0105 BOOST_MATH_BIG_CONSTANT(T, 64, -3.67192254707729348546)
0106 };
0107 BOOST_MATH_STATIC const T Q[] = {
0108 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0109 BOOST_MATH_BIG_CONSTANT(T, 64, 6.24264124854247537712),
0110 BOOST_MATH_BIG_CONSTANT(T, 64, 3.9713437953343869095),
0111 BOOST_MATH_BIG_CONSTANT(T, 64, -28.6608180499800029974),
0112 BOOST_MATH_BIG_CONSTANT(T, 64, -20.1432634680485188801),
0113 BOOST_MATH_BIG_CONSTANT(T, 64, 48.5609213108739935468),
0114 BOOST_MATH_BIG_CONSTANT(T, 64, 10.8268667355460159008),
0115 BOOST_MATH_BIG_CONSTANT(T, 64, -22.6436933413139721736),
0116 BOOST_MATH_BIG_CONSTANT(T, 64, 1.72114765761200282724)
0117 };
0118
0119 T g = sqrt(-2 * log(q));
0120 T xs = q - 0.25f;
0121 T r = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
0122 result = g / (Y + r);
0123 }
0124 else
0125 {
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 T x = sqrt(-log(q));
0146 if(x < 3)
0147 {
0148
0149
0150 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 0.807220458984375f;
0151 BOOST_MATH_STATIC const T P[] = {
0152 BOOST_MATH_BIG_CONSTANT(T, 64, -0.131102781679951906451),
0153 BOOST_MATH_BIG_CONSTANT(T, 64, -0.163794047193317060787),
0154 BOOST_MATH_BIG_CONSTANT(T, 64, 0.117030156341995252019),
0155 BOOST_MATH_BIG_CONSTANT(T, 64, 0.387079738972604337464),
0156 BOOST_MATH_BIG_CONSTANT(T, 64, 0.337785538912035898924),
0157 BOOST_MATH_BIG_CONSTANT(T, 64, 0.142869534408157156766),
0158 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0290157910005329060432),
0159 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00214558995388805277169),
0160 BOOST_MATH_BIG_CONSTANT(T, 64, -0.679465575181126350155e-6),
0161 BOOST_MATH_BIG_CONSTANT(T, 64, 0.285225331782217055858e-7),
0162 BOOST_MATH_BIG_CONSTANT(T, 64, -0.681149956853776992068e-9)
0163 };
0164 BOOST_MATH_STATIC const T Q[] = {
0165 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0166 BOOST_MATH_BIG_CONSTANT(T, 64, 3.46625407242567245975),
0167 BOOST_MATH_BIG_CONSTANT(T, 64, 5.38168345707006855425),
0168 BOOST_MATH_BIG_CONSTANT(T, 64, 4.77846592945843778382),
0169 BOOST_MATH_BIG_CONSTANT(T, 64, 2.59301921623620271374),
0170 BOOST_MATH_BIG_CONSTANT(T, 64, 0.848854343457902036425),
0171 BOOST_MATH_BIG_CONSTANT(T, 64, 0.152264338295331783612),
0172 BOOST_MATH_BIG_CONSTANT(T, 64, 0.01105924229346489121)
0173 };
0174
0175 T xs = x - 1.125f;
0176 T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
0177 result = Y * x + R * x;
0178 }
0179 else if(x < 6)
0180 {
0181
0182
0183 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 0.93995571136474609375f;
0184 BOOST_MATH_STATIC const T P[] = {
0185 BOOST_MATH_BIG_CONSTANT(T, 64, -0.0350353787183177984712),
0186 BOOST_MATH_BIG_CONSTANT(T, 64, -0.00222426529213447927281),
0187 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0185573306514231072324),
0188 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00950804701325919603619),
0189 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00187123492819559223345),
0190 BOOST_MATH_BIG_CONSTANT(T, 64, 0.000157544617424960554631),
0191 BOOST_MATH_BIG_CONSTANT(T, 64, 0.460469890584317994083e-5),
0192 BOOST_MATH_BIG_CONSTANT(T, 64, -0.230404776911882601748e-9),
0193 BOOST_MATH_BIG_CONSTANT(T, 64, 0.266339227425782031962e-11)
0194 };
0195 BOOST_MATH_STATIC const T Q[] = {
0196 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0197 BOOST_MATH_BIG_CONSTANT(T, 64, 1.3653349817554063097),
0198 BOOST_MATH_BIG_CONSTANT(T, 64, 0.762059164553623404043),
0199 BOOST_MATH_BIG_CONSTANT(T, 64, 0.220091105764131249824),
0200 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0341589143670947727934),
0201 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00263861676657015992959),
0202 BOOST_MATH_BIG_CONSTANT(T, 64, 0.764675292302794483503e-4)
0203 };
0204
0205 T xs = x - 3;
0206 T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
0207 result = Y * x + R * x;
0208 }
0209 else if(x < 18)
0210 {
0211
0212
0213 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 0.98362827301025390625f;
0214 BOOST_MATH_STATIC const T P[] = {
0215 BOOST_MATH_BIG_CONSTANT(T, 64, -0.0167431005076633737133),
0216 BOOST_MATH_BIG_CONSTANT(T, 64, -0.00112951438745580278863),
0217 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00105628862152492910091),
0218 BOOST_MATH_BIG_CONSTANT(T, 64, 0.000209386317487588078668),
0219 BOOST_MATH_BIG_CONSTANT(T, 64, 0.149624783758342370182e-4),
0220 BOOST_MATH_BIG_CONSTANT(T, 64, 0.449696789927706453732e-6),
0221 BOOST_MATH_BIG_CONSTANT(T, 64, 0.462596163522878599135e-8),
0222 BOOST_MATH_BIG_CONSTANT(T, 64, -0.281128735628831791805e-13),
0223 BOOST_MATH_BIG_CONSTANT(T, 64, 0.99055709973310326855e-16)
0224 };
0225 BOOST_MATH_STATIC const T Q[] = {
0226 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0227 BOOST_MATH_BIG_CONSTANT(T, 64, 0.591429344886417493481),
0228 BOOST_MATH_BIG_CONSTANT(T, 64, 0.138151865749083321638),
0229 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0160746087093676504695),
0230 BOOST_MATH_BIG_CONSTANT(T, 64, 0.000964011807005165528527),
0231 BOOST_MATH_BIG_CONSTANT(T, 64, 0.275335474764726041141e-4),
0232 BOOST_MATH_BIG_CONSTANT(T, 64, 0.282243172016108031869e-6)
0233 };
0234
0235 T xs = x - 6;
0236 T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
0237 result = Y * x + R * x;
0238 }
0239 else if(x < 44)
0240 {
0241
0242
0243 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 0.99714565277099609375f;
0244 BOOST_MATH_STATIC const T P[] = {
0245 BOOST_MATH_BIG_CONSTANT(T, 64, -0.0024978212791898131227),
0246 BOOST_MATH_BIG_CONSTANT(T, 64, -0.779190719229053954292e-5),
0247 BOOST_MATH_BIG_CONSTANT(T, 64, 0.254723037413027451751e-4),
0248 BOOST_MATH_BIG_CONSTANT(T, 64, 0.162397777342510920873e-5),
0249 BOOST_MATH_BIG_CONSTANT(T, 64, 0.396341011304801168516e-7),
0250 BOOST_MATH_BIG_CONSTANT(T, 64, 0.411632831190944208473e-9),
0251 BOOST_MATH_BIG_CONSTANT(T, 64, 0.145596286718675035587e-11),
0252 BOOST_MATH_BIG_CONSTANT(T, 64, -0.116765012397184275695e-17)
0253 };
0254 BOOST_MATH_STATIC const T Q[] = {
0255 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0256 BOOST_MATH_BIG_CONSTANT(T, 64, 0.207123112214422517181),
0257 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0169410838120975906478),
0258 BOOST_MATH_BIG_CONSTANT(T, 64, 0.000690538265622684595676),
0259 BOOST_MATH_BIG_CONSTANT(T, 64, 0.145007359818232637924e-4),
0260 BOOST_MATH_BIG_CONSTANT(T, 64, 0.144437756628144157666e-6),
0261 BOOST_MATH_BIG_CONSTANT(T, 64, 0.509761276599778486139e-9)
0262 };
0263
0264 T xs = x - 18;
0265 T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
0266 result = Y * x + R * x;
0267 }
0268 else
0269 {
0270
0271
0272 BOOST_MATH_STATIC_LOCAL_VARIABLE const float Y = 0.99941349029541015625f;
0273 BOOST_MATH_STATIC const T P[] = {
0274 BOOST_MATH_BIG_CONSTANT(T, 64, -0.000539042911019078575891),
0275 BOOST_MATH_BIG_CONSTANT(T, 64, -0.28398759004727721098e-6),
0276 BOOST_MATH_BIG_CONSTANT(T, 64, 0.899465114892291446442e-6),
0277 BOOST_MATH_BIG_CONSTANT(T, 64, 0.229345859265920864296e-7),
0278 BOOST_MATH_BIG_CONSTANT(T, 64, 0.225561444863500149219e-9),
0279 BOOST_MATH_BIG_CONSTANT(T, 64, 0.947846627503022684216e-12),
0280 BOOST_MATH_BIG_CONSTANT(T, 64, 0.135880130108924861008e-14),
0281 BOOST_MATH_BIG_CONSTANT(T, 64, -0.348890393399948882918e-21)
0282 };
0283 BOOST_MATH_STATIC const T Q[] = {
0284 BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
0285 BOOST_MATH_BIG_CONSTANT(T, 64, 0.0845746234001899436914),
0286 BOOST_MATH_BIG_CONSTANT(T, 64, 0.00282092984726264681981),
0287 BOOST_MATH_BIG_CONSTANT(T, 64, 0.468292921940894236786e-4),
0288 BOOST_MATH_BIG_CONSTANT(T, 64, 0.399968812193862100054e-6),
0289 BOOST_MATH_BIG_CONSTANT(T, 64, 0.161809290887904476097e-8),
0290 BOOST_MATH_BIG_CONSTANT(T, 64, 0.231558608310259605225e-11)
0291 };
0292
0293 T xs = x - 44;
0294 T R = tools::evaluate_polynomial(P, xs) / tools::evaluate_polynomial(Q, xs);
0295 result = Y * x + R * x;
0296 }
0297 }
0298 return result;
0299 }
0300
0301 template <class T, class Policy>
0302 struct erf_roots
0303 {
0304 boost::math::tuple<T,T,T> operator()(const T& guess)
0305 {
0306 BOOST_MATH_STD_USING
0307 T derivative = sign * (2 / sqrt(constants::pi<T>())) * exp(-(guess * guess));
0308 T derivative2 = -2 * guess * derivative;
0309 return boost::math::make_tuple(((sign > 0) ? static_cast<T>(boost::math::erf(guess, Policy()) - target) : static_cast<T>(boost::math::erfc(guess, Policy())) - target), derivative, derivative2);
0310 }
0311 erf_roots(T z, int s) : target(z), sign(s) {}
0312 private:
0313 T target;
0314 int sign;
0315 };
0316
0317 template <class T, class Policy>
0318 T erf_inv_imp(const T& p, const T& q, const Policy& pol, const std::integral_constant<int, 0>&)
0319 {
0320
0321
0322
0323 using tag_type = std::integral_constant<int, 64>;
0324 T guess = erf_inv_imp(p, q, pol, tag_type());
0325 T result;
0326
0327
0328
0329
0330 if(policies::digits<T, Policy>() > 64)
0331 {
0332 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0333 if(p <= 0.5)
0334 {
0335 result = tools::halley_iterate(detail::erf_roots<typename std::remove_cv<T>::type, Policy>(p, 1), guess, static_cast<T>(0), tools::max_value<T>(), (policies::digits<T, Policy>() * 2) / 3, max_iter);
0336 }
0337 else
0338 {
0339 result = tools::halley_iterate(detail::erf_roots<typename std::remove_cv<T>::type, Policy>(q, -1), guess, static_cast<T>(0), tools::max_value<T>(), (policies::digits<T, Policy>() * 2) / 3, max_iter);
0340 }
0341 policies::check_root_iterations<T>("boost::math::erf_inv<%1%>", max_iter, pol);
0342 }
0343 else
0344 {
0345 result = guess;
0346 }
0347 return result;
0348 }
0349
0350 }
0351
0352 template <class T, class Policy>
0353 BOOST_MATH_GPU_ENABLED typename tools::promote_args<T>::type erfc_inv(T z, const Policy& pol)
0354 {
0355 typedef typename tools::promote_args<T>::type result_type;
0356
0357
0358
0359
0360 constexpr auto function = "boost::math::erfc_inv<%1%>(%1%, %1%)";
0361 if((z < 0) || (z > 2))
0362 return policies::raise_domain_error<result_type>(function, "Argument outside range [0,2] in inverse erfc function (got p=%1%).", z, pol);
0363 if(z == 0)
0364 return policies::raise_overflow_error<result_type>(function, nullptr, pol);
0365 if(z == 2)
0366 return -policies::raise_overflow_error<result_type>(function, nullptr, pol);
0367
0368
0369
0370
0371
0372 result_type p, q, s;
0373 if(z > 1)
0374 {
0375 q = 2 - z;
0376 p = 1 - q;
0377 s = -1;
0378 }
0379 else
0380 {
0381 p = 1 - z;
0382 q = z;
0383 s = 1;
0384 }
0385
0386
0387
0388
0389 typedef typename policies::precision<result_type, Policy>::type precision_type;
0390 typedef std::integral_constant<int,
0391 precision_type::value <= 0 ? 0 :
0392 precision_type::value <= 64 ? 64 : 0
0393 > tag_type;
0394
0395
0396
0397
0398 typedef typename policies::evaluation<result_type, Policy>::type eval_type;
0399 typedef typename policies::normalise<
0400 Policy,
0401 policies::promote_float<false>,
0402 policies::promote_double<false>,
0403 policies::discrete_quantile<>,
0404 policies::assert_undefined<> >::type forwarding_policy;
0405
0406
0407
0408
0409 return s * policies::checked_narrowing_cast<result_type, forwarding_policy>(
0410 detail::erf_inv_imp(static_cast<eval_type>(p), static_cast<eval_type>(q), forwarding_policy(), tag_type()), function);
0411 }
0412
0413 template <class T, class Policy>
0414 BOOST_MATH_GPU_ENABLED typename tools::promote_args<T>::type erf_inv(T z, const Policy& pol)
0415 {
0416 typedef typename tools::promote_args<T>::type result_type;
0417
0418
0419
0420
0421 constexpr auto function = "boost::math::erf_inv<%1%>(%1%, %1%)";
0422 if((z < -1) || (z > 1))
0423 return policies::raise_domain_error<result_type>(function, "Argument outside range [-1, 1] in inverse erf function (got p=%1%).", z, pol);
0424 if(z == 1)
0425 return policies::raise_overflow_error<result_type>(function, nullptr, pol);
0426 if(z == -1)
0427 return -policies::raise_overflow_error<result_type>(function, nullptr, pol);
0428 if(z == 0)
0429 return 0;
0430
0431
0432
0433
0434
0435 result_type p, q, s;
0436 if(z < 0)
0437 {
0438 p = -z;
0439 q = 1 - p;
0440 s = -1;
0441 }
0442 else
0443 {
0444 p = z;
0445 q = 1 - z;
0446 s = 1;
0447 }
0448
0449
0450
0451
0452 typedef typename policies::precision<result_type, Policy>::type precision_type;
0453 typedef std::integral_constant<int,
0454 precision_type::value <= 0 ? 0 :
0455 precision_type::value <= 64 ? 64 : 0
0456 > tag_type;
0457
0458
0459
0460
0461 typedef typename policies::evaluation<result_type, Policy>::type eval_type;
0462 typedef typename policies::normalise<
0463 Policy,
0464 policies::promote_float<false>,
0465 policies::promote_double<false>,
0466 policies::discrete_quantile<>,
0467 policies::assert_undefined<> >::type forwarding_policy;
0468
0469
0470
0471
0472 typedef typename policies::evaluation<result_type, Policy>::type eval_type;
0473
0474
0475
0476
0477 return s * policies::checked_narrowing_cast<result_type, forwarding_policy>(
0478 detail::erf_inv_imp(static_cast<eval_type>(p), static_cast<eval_type>(q), forwarding_policy(), tag_type()), function);
0479 }
0480
0481 template <class T>
0482 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type erfc_inv(T z)
0483 {
0484 return erfc_inv(z, policies::policy<>());
0485 }
0486
0487 template <class T>
0488 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type erf_inv(T z)
0489 {
0490 return erf_inv(z, policies::policy<>());
0491 }
0492
0493 }
0494 }
0495
0496 #else
0497
0498 namespace boost {
0499 namespace math {
0500
0501 template <typename T>
0502 BOOST_MATH_GPU_ENABLED auto erf_inv(T x)
0503 {
0504 return ::erfinv(x);
0505 }
0506
0507 template <>
0508 BOOST_MATH_GPU_ENABLED auto erf_inv(float x)
0509 {
0510 return ::erfinvf(x);
0511 }
0512
0513 template <typename T, typename Policy>
0514 BOOST_MATH_GPU_ENABLED auto erf_inv(T x, const Policy&)
0515 {
0516 return ::erfinv(x);
0517 }
0518
0519 template <typename Policy>
0520 BOOST_MATH_GPU_ENABLED auto erf_inv(float x, const Policy&)
0521 {
0522 return ::erfinvf(x);
0523 }
0524
0525 template <typename T>
0526 BOOST_MATH_GPU_ENABLED auto erfc_inv(T x)
0527 {
0528 return ::erfcinv(x);
0529 }
0530
0531 template <>
0532 BOOST_MATH_GPU_ENABLED auto erfc_inv(float x)
0533 {
0534 return ::erfcinvf(x);
0535 }
0536
0537 template <typename T, typename Policy>
0538 BOOST_MATH_GPU_ENABLED auto erfc_inv(T x, const Policy&)
0539 {
0540 return ::erfcinv(x);
0541 }
0542
0543 template <typename Policy>
0544 BOOST_MATH_GPU_ENABLED auto erfc_inv(float x, const Policy&)
0545 {
0546 return ::erfcinvf(x);
0547 }
0548
0549 }
0550 }
0551
0552 #endif
0553
0554 #ifdef _MSC_VER
0555 #pragma warning(pop)
0556 #endif
0557
0558 #endif
0559