| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Copyright 2023 John Maddock. Distributed under the Boost |
| 3 | // Software License, Version 1.0. (See accompanying file |
| 4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 5 | |
| 6 | #ifndef BOOST_MP_FWD_HPP |
| 7 | #define BOOST_MP_FWD_HPP |
| 8 | |
| 9 | #include <boost/multiprecision/cpp_int/cpp_int_config.hpp> |
| 10 | |
| 11 | namespace boost { |
| 12 | namespace multiprecision { |
| 13 | |
| 14 | enum expression_template_option |
| 15 | { |
| 16 | et_off = 0, |
| 17 | et_on = 1 |
| 18 | }; |
| 19 | |
| 20 | template <class Backend> |
| 21 | struct expression_template_default |
| 22 | { |
| 23 | static constexpr expression_template_option value = et_on; |
| 24 | }; |
| 25 | |
| 26 | template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value> |
| 27 | class number; |
| 28 | |
| 29 | template <class T> |
| 30 | struct is_number : public std::integral_constant<bool, false> |
| 31 | {}; |
| 32 | |
| 33 | template <class Backend, expression_template_option ExpressionTemplates> |
| 34 | struct is_number<number<Backend, ExpressionTemplates> > : public std::integral_constant<bool, true> |
| 35 | {}; |
| 36 | |
| 37 | namespace detail { |
| 38 | |
| 39 | // Forward-declare an expression wrapper |
| 40 | template <class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void> |
| 41 | struct expression; |
| 42 | |
| 43 | } // namespace detail |
| 44 | |
| 45 | enum cpp_integer_type |
| 46 | { |
| 47 | signed_magnitude = 1, |
| 48 | unsigned_magnitude = 0, |
| 49 | signed_packed = 3, |
| 50 | unsigned_packed = 2 |
| 51 | }; |
| 52 | |
| 53 | enum cpp_int_check_type |
| 54 | { |
| 55 | checked = 1, |
| 56 | unchecked = 0 |
| 57 | }; |
| 58 | |
| 59 | enum mpfr_allocation_type |
| 60 | { |
| 61 | allocate_stack, |
| 62 | allocate_dynamic |
| 63 | }; |
| 64 | |
| 65 | template <class Backend> |
| 66 | void log_postfix_event(const Backend&, const char* /*event_description*/); |
| 67 | template <class Backend, class T> |
| 68 | void log_postfix_event(const Backend&, const T&, const char* /*event_description*/); |
| 69 | template <class Backend> |
| 70 | void log_prefix_event(const Backend&, const char* /*event_description*/); |
| 71 | template <class Backend, class T> |
| 72 | void log_prefix_event(const Backend&, const T&, const char* /*event_description*/); |
| 73 | template <class Backend, class T, class U> |
| 74 | void log_prefix_event(const Backend&, const T&, const U&, const char* /*event_description*/); |
| 75 | template <class Backend, class T, class U, class V> |
| 76 | void log_prefix_event(const Backend&, const T&, const U&, const V&, const char* /*event_description*/); |
| 77 | |
| 78 | namespace backends { |
| 79 | |
| 80 | template <class Backend> |
| 81 | struct debug_adaptor; |
| 82 | |
| 83 | template <class Backend> |
| 84 | struct logged_adaptor; |
| 85 | |
| 86 | template <class Backend> |
| 87 | struct complex_adaptor; |
| 88 | |
| 89 | enum digit_base_type |
| 90 | { |
| 91 | digit_base_2 = 2, |
| 92 | digit_base_10 = 10 |
| 93 | }; |
| 94 | |
| 95 | template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0> |
| 96 | class cpp_bin_float; |
| 97 | |
| 98 | template <unsigned Digits10, class ExponentType = std::int32_t, class Allocator = void> |
| 99 | class cpp_dec_float; |
| 100 | |
| 101 | template <std::size_t MinBits = 0, std::size_t MaxBits = 0, boost::multiprecision::cpp_integer_type SignType = signed_magnitude, cpp_int_check_type Checked = unchecked, class Allocator = typename std::conditional<MinBits && (MinBits == MaxBits), void, std::allocator<limb_type> >::type> |
| 102 | struct cpp_int_backend; |
| 103 | |
| 104 | struct float128_backend; |
| 105 | |
| 106 | struct gmp_int; |
| 107 | struct gmp_rational; |
| 108 | |
| 109 | template <unsigned digits10> |
| 110 | struct gmp_float; |
| 111 | |
| 112 | template <unsigned digits10> |
| 113 | struct mpc_complex_backend; |
| 114 | |
| 115 | template <unsigned digits10> |
| 116 | struct mpfi_float_backend; |
| 117 | |
| 118 | template <unsigned digits10, mpfr_allocation_type AllocationType = allocate_dynamic> |
| 119 | struct mpfr_float_backend; |
| 120 | |
| 121 | template <> |
| 122 | struct mpfr_float_backend<0, allocate_stack>; |
| 123 | |
| 124 | template <class Backend> |
| 125 | struct rational_adaptor; |
| 126 | |
| 127 | struct tommath_int; |
| 128 | } |
| 129 | |
| 130 | using boost::multiprecision::backends::complex_adaptor; |
| 131 | using boost::multiprecision::backends::debug_adaptor; |
| 132 | using boost::multiprecision::backends::logged_adaptor; |
| 133 | using backends::cpp_bin_float; |
| 134 | using backends::digit_base_10; |
| 135 | using backends::digit_base_2; |
| 136 | using boost::multiprecision::backends::cpp_dec_float; |
| 137 | using boost::multiprecision::backends::cpp_int_backend; |
| 138 | using boost::multiprecision::backends::float128_backend; |
| 139 | using boost::multiprecision::backends::gmp_float; |
| 140 | using boost::multiprecision::backends::gmp_int; |
| 141 | using boost::multiprecision::backends::gmp_rational; |
| 142 | using boost::multiprecision::backends::mpc_complex_backend; |
| 143 | using boost::multiprecision::backends::mpfi_float_backend; |
| 144 | using boost::multiprecision::backends::mpfr_float_backend; |
| 145 | using boost::multiprecision::backends::rational_adaptor; |
| 146 | using boost::multiprecision::backends::tommath_int; |
| 147 | |
| 148 | template <unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
| 149 | struct expression_template_default<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > |
| 150 | { |
| 151 | static constexpr expression_template_option value = std::is_void<Allocator>::value ? et_off : et_on; |
| 152 | }; |
| 153 | |
| 154 | template <std::size_t MinBits, std::size_t MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked> |
| 155 | struct expression_template_default<backends::cpp_int_backend<MinBits, MaxBits, SignType, Checked, void> > |
| 156 | { |
| 157 | static constexpr expression_template_option value = et_off; |
| 158 | }; |
| 159 | |
| 160 | template <class IntBackend> |
| 161 | struct expression_template_default<backends::rational_adaptor<IntBackend> > : public expression_template_default<IntBackend> |
| 162 | {}; |
| 163 | |
| 164 | using complex128 = number<complex_adaptor<float128_backend>, et_off>; |
| 165 | |
| 166 | using cpp_bin_float_50 = number<backends::cpp_bin_float<50> >; |
| 167 | using cpp_bin_float_100 = number<backends::cpp_bin_float<100> >; |
| 168 | |
| 169 | using cpp_bin_float_single = number<backends::cpp_bin_float<24, backends::digit_base_2, void, std::int16_t, -126, 127>, et_off>; |
| 170 | using cpp_bin_float_double = number<backends::cpp_bin_float<53, backends::digit_base_2, void, std::int16_t, -1022, 1023>, et_off>; |
| 171 | using cpp_bin_float_double_extended = number<backends::cpp_bin_float<64, backends::digit_base_2, void, std::int16_t, -16382, 16383>, et_off>; |
| 172 | using cpp_bin_float_quad = number<backends::cpp_bin_float<113, backends::digit_base_2, void, std::int16_t, -16382, 16383>, et_off>; |
| 173 | using cpp_bin_float_oct = number<backends::cpp_bin_float<237, backends::digit_base_2, void, std::int32_t, -262142, 262143>, et_off>; |
| 174 | |
| 175 | template <unsigned Digits, backends::digit_base_type DigitBase = backends::digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0> |
| 176 | using cpp_complex_backend = complex_adaptor<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >; |
| 177 | |
| 178 | template <unsigned Digits, backends::digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0, expression_template_option ExpressionTemplates = et_off> |
| 179 | using cpp_complex = number<complex_adaptor<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >, ExpressionTemplates>; |
| 180 | |
| 181 | using cpp_complex_50 = cpp_complex<50>; |
| 182 | using cpp_complex_100 = cpp_complex<100>; |
| 183 | |
| 184 | using cpp_complex_single = cpp_complex<24, backends::digit_base_2, void, std::int16_t, -126, 127>; |
| 185 | using cpp_complex_double = cpp_complex<53, backends::digit_base_2, void, std::int16_t, -1022, 1023>; |
| 186 | using cpp_complex_extended = cpp_complex<64, backends::digit_base_2, void, std::int16_t, -16382, 16383>; |
| 187 | using cpp_complex_quad = cpp_complex<113, backends::digit_base_2, void, std::int16_t, -16382, 16383>; |
| 188 | using cpp_complex_oct = cpp_complex<237, backends::digit_base_2, void, std::int32_t, -262142, 262143>; |
| 189 | |
| 190 | using cpp_dec_float_50 = number<cpp_dec_float<50> >; |
| 191 | using cpp_dec_float_100 = number<cpp_dec_float<100> >; |
| 192 | |
| 193 | using cpp_int = number<cpp_int_backend<> >; |
| 194 | using cpp_rational_backend = rational_adaptor<cpp_int_backend<> >; |
| 195 | using cpp_rational = number<cpp_rational_backend>; |
| 196 | |
| 197 | // Fixed precision unsigned types: |
| 198 | using uint128_t = number<cpp_int_backend<128, 128, unsigned_magnitude, unchecked, void> >; |
| 199 | using uint256_t = number<cpp_int_backend<256, 256, unsigned_magnitude, unchecked, void> >; |
| 200 | using uint512_t = number<cpp_int_backend<512, 512, unsigned_magnitude, unchecked, void> >; |
| 201 | using uint1024_t = number<cpp_int_backend<1024, 1024, unsigned_magnitude, unchecked, void> >; |
| 202 | |
| 203 | // Fixed precision signed types: |
| 204 | using int128_t = number<cpp_int_backend<128, 128, signed_magnitude, unchecked, void> >; |
| 205 | using int256_t = number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> >; |
| 206 | using int512_t = number<cpp_int_backend<512, 512, signed_magnitude, unchecked, void> >; |
| 207 | using int1024_t = number<cpp_int_backend<1024, 1024, signed_magnitude, unchecked, void> >; |
| 208 | |
| 209 | // Over again, but with checking enabled this time: |
| 210 | using checked_cpp_int = number<cpp_int_backend<0, 0, signed_magnitude, checked> >; |
| 211 | using checked_cpp_rational_backend = rational_adaptor<cpp_int_backend<0, 0, signed_magnitude, checked> >; |
| 212 | using checked_cpp_rational = number<checked_cpp_rational_backend>; |
| 213 | // Fixed precision unsigned types: |
| 214 | using checked_uint128_t = number<cpp_int_backend<128, 128, unsigned_magnitude, checked, void> >; |
| 215 | using checked_uint256_t = number<cpp_int_backend<256, 256, unsigned_magnitude, checked, void> >; |
| 216 | using checked_uint512_t = number<cpp_int_backend<512, 512, unsigned_magnitude, checked, void> >; |
| 217 | using checked_uint1024_t = number<cpp_int_backend<1024, 1024, unsigned_magnitude, checked, void> >; |
| 218 | |
| 219 | // Fixed precision signed types: |
| 220 | using checked_int128_t = number<cpp_int_backend<128, 128, signed_magnitude, checked, void> >; |
| 221 | using checked_int256_t = number<cpp_int_backend<256, 256, signed_magnitude, checked, void> >; |
| 222 | using checked_int512_t = number<cpp_int_backend<512, 512, signed_magnitude, checked, void> >; |
| 223 | using checked_int1024_t = number<cpp_int_backend<1024, 1024, signed_magnitude, checked, void> >; |
| 224 | |
| 225 | template <class Number> |
| 226 | using debug_adaptor_t = number<debug_adaptor<typename Number::backend_type>, Number::et>; |
| 227 | template <class Number> |
| 228 | using logged_adaptor_t = number<logged_adaptor<typename Number::backend_type>, Number::et>; |
| 229 | |
| 230 | |
| 231 | using float128 = number<float128_backend, et_off>; |
| 232 | |
| 233 | using mpf_float_50 = number<gmp_float<50> >; |
| 234 | using mpf_float_100 = number<gmp_float<100> >; |
| 235 | using mpf_float_500 = number<gmp_float<500> >; |
| 236 | using mpf_float_1000 = number<gmp_float<1000> >; |
| 237 | using mpf_float = number<gmp_float<0> >; |
| 238 | using mpz_int = number<gmp_int>; |
| 239 | using mpq_rational = number<gmp_rational>; |
| 240 | |
| 241 | using mpc_complex_50 = number<mpc_complex_backend<50> >; |
| 242 | using mpc_complex_100 = number<mpc_complex_backend<100> >; |
| 243 | using mpc_complex_500 = number<mpc_complex_backend<500> >; |
| 244 | using mpc_complex_1000 = number<mpc_complex_backend<1000> >; |
| 245 | using mpc_complex = number<mpc_complex_backend<0> >; |
| 246 | |
| 247 | using mpfi_float_50 = number<mpfi_float_backend<50> >; |
| 248 | using mpfi_float_100 = number<mpfi_float_backend<100> >; |
| 249 | using mpfi_float_500 = number<mpfi_float_backend<500> >; |
| 250 | using mpfi_float_1000 = number<mpfi_float_backend<1000> >; |
| 251 | using mpfi_float = number<mpfi_float_backend<0> >; |
| 252 | |
| 253 | using mpfr_float_50 = number<mpfr_float_backend<50> >; |
| 254 | using mpfr_float_100 = number<mpfr_float_backend<100> >; |
| 255 | using mpfr_float_500 = number<mpfr_float_backend<500> >; |
| 256 | using mpfr_float_1000 = number<mpfr_float_backend<1000> >; |
| 257 | using mpfr_float = number<mpfr_float_backend<0> >; |
| 258 | |
| 259 | using static_mpfr_float_50 = number<mpfr_float_backend<50, allocate_stack> >; |
| 260 | using static_mpfr_float_100 = number<mpfr_float_backend<100, allocate_stack> >; |
| 261 | |
| 262 | using tom_int = number<tommath_int>; |
| 263 | using tommath_rational = rational_adaptor<tommath_int>; |
| 264 | using tom_rational = number<tommath_rational>; |
| 265 | |
| 266 | } } |
| 267 | |
| 268 | #endif |
| 269 | |