<#include<boost/multiprecision/mpfr.hpp>>
namespace boost{ namespace multiprecision{
enum mpfr_allocation_type
{
allocate_stack,
allocate_dynamic
};
template <unsigned Digits10, mpfr_allocation_type AllocateType = allocate_dynamic>
class mpfr_float_backend;
typedef number<mpfr_float_backend<50> > mpfr_float_50;
typedef number<mpfr_float_backend<100> > mpfr_float_100;
typedef number<mpfr_float_backend<500> > mpfr_float_500;
typedef number<mpfr_float_backend<1000> > mpfr_float_1000;
typedef number<mpfr_float_backend<0> > mpfr_float;
typedef number<mpfr_float_backend<50, allocate_stack> > static_mpfr_float_50;
typedef number<mpfr_float_backend<100, allocate_stack> > static_mpfr_float_100;
}}
<mpfr_float_backend>используется совместно с<number>: Он действует как тонкая обертка вокругMPFR<mpfr_t>, чтобы обеспечить тип реального числа, который является заменой для нативных типов плавающих точек C++, но с гораздо большей точностью.
Тип<mpfr_float_backend>можно использовать с фиксированной точностью, указав ненулевой<Digits10>параметр шаблона, или с переменной точностью, установив аргумент шаблона до нуля. Типдефы mpfr_float_50, mpfr_float_100, mpfr_float_500, mpfr_float_1000 обеспечивают арифметические типы с точностью 50, 100, 500 и 1000 десятичных знаков соответственно. Typedef mpfr_float обеспечивает переменный тип точности, точность которого может управляться через функции<number>.
Кроме того, второй параметр шаблона позволяет выбирать между динамическим распределением (по умолчанию и использует обычные процедуры распределения MPFR) или распределением стека (где вся память, необходимая для базовых типов данных, хранится в<mpfr_float_backend>). Последний вариант может привести к значительно более быстрому кодированию за счет увеличения размера<mpfr_float_backend>. Он может использоваться только с фиксированной точностью и должен использоваться только для более низких цифр. Обратите внимание, что мы не можем гарантировать, что использование<allocate_stack>не вызовет каких-либо вызовов для процедур распределения mpfr, поскольку mpfr может вызывать их внутри своего собственного кода. Следующая таблица дает представление о компромиссе производительности при 50 десятичных цифрах точности:
![[Note]](/img/note.png) |
Note |
Этот тип обеспечивает поддержку<numeric_limits>только тогда, когда точность фиксируется во время компиляции. |
Как и обычные преобразования из арифметических и струнных типов, экземпляры<number<mpfr_float_backend<N>>>являются копируемыми и присваиваемыми из:
- GMPродные типы<
mpf_t>,<mpz_t>,<mpq_t>.
- MPFRнативный тип<
mpfr_t>.
- <
number>обертывается вокруг этих типов:<number<mpfr_float_backend<M>>>,<number<mpf_float<M>>>,<number<gmp_int>>,<number<gmp_rational>>.
Также можно получить доступ к базовому<mpfr_t>через функцию<mpfr_float_backend>элемента данных.
Что вы должны знать при использовании этого типа:
- По умолчанию<
mpfr_float_backend>устанавливается на NaN (это поведение по умолчаниюMPFR).
- Все операции проходят в обход ближайших.
- Не вносятся изменения вGMPилиMPFRглобальные настройки, поэтому этот тип может сосуществовать с существующимMPFRилиGMPкодом.
- Код может в равной степени использоватьMPIRвместоGMP— действительно, это предпочтительный вариант на Win32.
- Этот бэкэнд поддерживает rvalue-ссылки и является Move-Aware, делая выводы<
number>об этом бэкэнд-движении осведомленными.
- Преобразование из строки приводит к тому, что<
std::runtime_error>выбрасывается, если строка не может быть интерпретирована как действительное число с плавающей точкой.
- Разделение на ноль приводит к бесконечности.
#include <boost/multiprecision/mpfr.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <iostream>
int main()
{
using namespace boost::multiprecision;
mpfr_float a = 2;
mpfr_float::default_precision(1000);
std::cout << mpfr_float::default_precision() << std::endl;
std::cout << sqrt(a) << std::endl;
mpfr_float_100 b = 2;
std::cout << std::numeric_limits<mpfr_float_100>::digits << std::endl;
std::cout << log(b) << std::endl;
std::cout << boost::math::tgamma(b) << std::endl;
std::cout << boost::math::tgamma(b * b) << std::endl;
mpfr_t r;
mpfr_init(r);
mpfr_set(r, b.backend().data(), GMP_RNDN);
mpfr_clear(r);
return 0;
}