File indexing completed on 2025-01-18 09:40:40
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MATH_TOOLS_FRACTION_INCLUDED
0007 #define BOOST_MATH_TOOLS_FRACTION_INCLUDED
0008
0009 #ifdef _MSC_VER
0010 #pragma once
0011 #endif
0012
0013 #include <boost/math/tools/precision.hpp>
0014 #include <boost/math/tools/complex.hpp>
0015 #include <type_traits>
0016 #include <cstdint>
0017 #include <cmath>
0018
0019 namespace boost{ namespace math{ namespace tools{
0020
0021 namespace detail
0022 {
0023
0024 template <typename T>
0025 struct is_pair : public std::false_type{};
0026
0027 template <typename T, typename U>
0028 struct is_pair<std::pair<T,U>> : public std::true_type{};
0029
0030 template <typename Gen>
0031 struct fraction_traits_simple
0032 {
0033 using result_type = typename Gen::result_type;
0034 using value_type = typename Gen::result_type;
0035
0036 static result_type a(const value_type&) BOOST_MATH_NOEXCEPT(value_type)
0037 {
0038 return 1;
0039 }
0040 static result_type b(const value_type& v) BOOST_MATH_NOEXCEPT(value_type)
0041 {
0042 return v;
0043 }
0044 };
0045
0046 template <typename Gen>
0047 struct fraction_traits_pair
0048 {
0049 using value_type = typename Gen::result_type;
0050 using result_type = typename value_type::first_type;
0051
0052 static result_type a(const value_type& v) BOOST_MATH_NOEXCEPT(value_type)
0053 {
0054 return v.first;
0055 }
0056 static result_type b(const value_type& v) BOOST_MATH_NOEXCEPT(value_type)
0057 {
0058 return v.second;
0059 }
0060 };
0061
0062 template <typename Gen>
0063 struct fraction_traits
0064 : public std::conditional<
0065 is_pair<typename Gen::result_type>::value,
0066 fraction_traits_pair<Gen>,
0067 fraction_traits_simple<Gen>>::type
0068 {
0069 };
0070
0071 template <typename T, bool = is_complex_type<T>::value>
0072 struct tiny_value
0073 {
0074
0075
0076
0077 static T get() {
0078 return 16*tools::min_value<T>();
0079 }
0080 };
0081 template <typename T>
0082 struct tiny_value<T, true>
0083 {
0084 using value_type = typename T::value_type;
0085 static T get() {
0086 return 16*tools::min_value<value_type>();
0087 }
0088 };
0089
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 template <typename Gen, typename U>
0107 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_b(Gen& g, const U& factor, std::uintmax_t& max_terms)
0108 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0109 {
0110 BOOST_MATH_STD_USING
0111
0112 using traits = detail::fraction_traits<Gen>;
0113 using result_type = typename traits::result_type;
0114 using value_type = typename traits::value_type;
0115 using integer_type = typename integer_scalar_type<result_type>::type;
0116 using scalar_type = typename scalar_type<result_type>::type;
0117
0118 integer_type const zero(0), one(1);
0119
0120 result_type tiny = detail::tiny_value<result_type>::get();
0121 scalar_type terminator = abs(factor);
0122
0123 value_type v = g();
0124
0125 result_type f, C, D, delta;
0126 f = traits::b(v);
0127 if(f == zero)
0128 f = tiny;
0129 C = f;
0130 D = 0;
0131
0132 std::uintmax_t counter(max_terms);
0133 do{
0134 v = g();
0135 D = traits::b(v) + traits::a(v) * D;
0136 if(D == result_type(0))
0137 D = tiny;
0138 C = traits::b(v) + traits::a(v) / C;
0139 if(C == zero)
0140 C = tiny;
0141 D = one/D;
0142 delta = C*D;
0143 f = f * delta;
0144 }while((abs(delta - one) > terminator) && --counter);
0145
0146 max_terms = max_terms - counter;
0147
0148 return f;
0149 }
0150
0151 template <typename Gen, typename U>
0152 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_b(Gen& g, const U& factor)
0153 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0154 {
0155 std::uintmax_t max_terms = (std::numeric_limits<std::uintmax_t>::max)();
0156 return continued_fraction_b(g, factor, max_terms);
0157 }
0158
0159 template <typename Gen>
0160 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_b(Gen& g, int bits)
0161 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0162 {
0163 BOOST_MATH_STD_USING
0164
0165 using traits = detail::fraction_traits<Gen>;
0166 using result_type = typename traits::result_type;
0167
0168 result_type factor = ldexp(1.0f, 1 - bits);
0169 std::uintmax_t max_terms = (std::numeric_limits<std::uintmax_t>::max)();
0170 return continued_fraction_b(g, factor, max_terms);
0171 }
0172
0173 template <typename Gen>
0174 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_b(Gen& g, int bits, std::uintmax_t& max_terms)
0175 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0176 {
0177 BOOST_MATH_STD_USING
0178
0179 using traits = detail::fraction_traits<Gen>;
0180 using result_type = typename traits::result_type;
0181
0182 result_type factor = ldexp(1.0f, 1 - bits);
0183 return continued_fraction_b(g, factor, max_terms);
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 template <typename Gen, typename U>
0201 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_a(Gen& g, const U& factor, std::uintmax_t& max_terms)
0202 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0203 {
0204 BOOST_MATH_STD_USING
0205
0206 using traits = detail::fraction_traits<Gen>;
0207 using result_type = typename traits::result_type;
0208 using value_type = typename traits::value_type;
0209 using integer_type = typename integer_scalar_type<result_type>::type;
0210 using scalar_type = typename scalar_type<result_type>::type;
0211
0212 integer_type const zero(0), one(1);
0213
0214 result_type tiny = detail::tiny_value<result_type>::get();
0215 scalar_type terminator = abs(factor);
0216
0217 value_type v = g();
0218
0219 result_type f, C, D, delta, a0;
0220 f = traits::b(v);
0221 a0 = traits::a(v);
0222 if(f == zero)
0223 f = tiny;
0224 C = f;
0225 D = 0;
0226
0227 std::uintmax_t counter(max_terms);
0228
0229 do{
0230 v = g();
0231 D = traits::b(v) + traits::a(v) * D;
0232 if(D == zero)
0233 D = tiny;
0234 C = traits::b(v) + traits::a(v) / C;
0235 if(C == zero)
0236 C = tiny;
0237 D = one/D;
0238 delta = C*D;
0239 f = f * delta;
0240 }while((abs(delta - one) > terminator) && --counter);
0241
0242 max_terms = max_terms - counter;
0243
0244 return a0/f;
0245 }
0246
0247 template <typename Gen, typename U>
0248 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_a(Gen& g, const U& factor)
0249 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0250 {
0251 std::uintmax_t max_iter = (std::numeric_limits<std::uintmax_t>::max)();
0252 return continued_fraction_a(g, factor, max_iter);
0253 }
0254
0255 template <typename Gen>
0256 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_a(Gen& g, int bits)
0257 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0258 {
0259 BOOST_MATH_STD_USING
0260
0261 typedef detail::fraction_traits<Gen> traits;
0262 typedef typename traits::result_type result_type;
0263
0264 result_type factor = ldexp(1.0f, 1-bits);
0265 std::uintmax_t max_iter = (std::numeric_limits<std::uintmax_t>::max)();
0266
0267 return continued_fraction_a(g, factor, max_iter);
0268 }
0269
0270 template <typename Gen>
0271 inline typename detail::fraction_traits<Gen>::result_type continued_fraction_a(Gen& g, int bits, std::uintmax_t& max_terms)
0272 noexcept(BOOST_MATH_IS_FLOAT(typename detail::fraction_traits<Gen>::result_type) && noexcept(std::declval<Gen>()()))
0273 {
0274 BOOST_MATH_STD_USING
0275
0276 using traits = detail::fraction_traits<Gen>;
0277 using result_type = typename traits::result_type;
0278
0279 result_type factor = ldexp(1.0f, 1-bits);
0280 return continued_fraction_a(g, factor, max_terms);
0281 }
0282
0283 }
0284 }
0285 }
0286
0287 #endif