Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Defining a Special Function.

Boost , Chapter 1. Boost.Multiprecision , Examples

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

В этом примере мы покажем несколько реализаций функцииJahnke и Emden Lambda, каждая из которых немного сложнее предыдущей.

Функция Янке-Эмдена Ламбда определяется уравнением:

JahnkeEmden(v, z) = Γ(v+1) * Jv(z) / (z/2)v

Если бы мы реализовали это с двойной точностью с помощью Boost. Средства математики для функции Гаммы и Бесселя выглядят так:

double JEL1(double v, double z)
{
   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / std::pow(z / 2, v);
}

Назвать эту функцию:

std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::digits10);
std::cout << JEL1(2.5, 0.5) << std::endl;

Производительность:

9.822663964796047e-001

Теперь давайте снова реализуем функцию, но на этот раз с помощью многоточного типа<cpp_dec_float_50>в качестве аргументного типа:

boost::multiprecision::cpp_dec_float_50
   JEL2(boost::multiprecision::cpp_dec_float_50 v, boost::multiprecision::cpp_dec_float_50 z)
{
   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / boost::multiprecision::pow(z / 2, v);
}

Реализация почти такая же, как и раньше, но с одним ключевым отличием - мы больше не можем называть<std::pow>, вместо этого мы должны называть версию внутри<boost::multiprecision>пространства имен. На самом деле, мы могли бы опустить префикс пространства имен при вызове<pow>, поскольку правильная перегрузка была бы найдена черезаргументированный поискв любом случае.

Обратите внимание, что первый аргумент<pow>вместе с аргументом<tgamma>в приведенном выше коде на самом деле являются шаблонами выражения. Эти<pow>и<tgamma>функции прекрасно справятся с этими аргументами.

Вот пример того, как функция может быть названа:

std::cout << std::scientific << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10);
std::cout << JEL2(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl;

Какие выходы:

9.82266396479604757017335009796882833995903762577173e-01

Теперь, когда мы увидели некоторые примеры без шаблонов, давайте повторим код снова, но на этот раз в качестве шаблона, который можно назвать либо со встроенным типом<float>,<double>и т. Д.

template <class Float>
Float JEL3(Float v, Float z)
{
   using std::pow;
   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / pow(z / 2, v);
}

Код снова почти такой же, как и раньше, но призыв к<pow>снова изменился. Нам нужен призыв к решению либо<std::pow>(когда аргумент является встроенным типом), либо<boost::multiprecision::pow>(когда аргумент является многоточным типом). Мы делаем это, делая вызов неквалифицированным, чтобы версии<pow>, определенные в том же пространстве имен, что и тип<Float>, были найдены с помощью поиска, зависящего от аргументов, в то время как директива<using std::pow>делает стандартные версии библиотеки видимыми для встроенных типов с плавающей запятой.

Назовем функцию с аргументами<double>и многоточностью:

std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::digits10);
std::cout << JEL3(2.5, 0.5) << std::endl;
std::cout << std::scientific << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10);
std::cout << JEL3(cpp_dec_float_50(2.5), cpp_dec_float_50(0.5)) << std::endl;

Какие выходы:

9.822663964796047e-001
9.82266396479604757017335009796882833995903762577173e-01

К сожалению, есть проблема с этой версией: если бы мы назвали ее так:

boost::multiprecision::cpp_dec_float_50 v(2), z(0.5);
JEL3(v + 0.5, z);

Тогда мы получим длинное и непостижимое сообщение об ошибке от компилятора: проблема здесь в том, что первый аргумент к<JEL3>не тип числа, а шаблон выражения. Очевидно, мы могли бы добавить тип-каст, чтобы решить проблему:

JEL(cpp_dec_float_50(v + 0.5), z);

Однако, если мы хотим, чтобы функция JEL была действительно многоразовой, то может быть предпочтительным лучшее решение. Для этого мы можем заимствовать код у Boost. Математика, которая вычисляет тип возврата функций смешанного аргумента, вот как теперь выглядит новый код:

template <class Float1, class Float2>
typename boost::math::tools::promote_args<Float1, Float2>::type
   JEL4(Float1 v, Float2 z)
{
   using std::pow;
   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / pow(z / 2, v);
}

Как вы можете видеть, два аргумента для функции теперь являются отдельными типами шаблонов, а тип возврата вычисляется с использованием метафункции<promote_args>от Boost. Математика.

Теперь мы можем позвонить:

std::cout << std::scientific << std::setprecision(std::numeric_limits<cpp_dec_float_100>::digits10);
std::cout << JEL4(cpp_dec_float_100(2) + 0.5, cpp_dec_float_100(0.5)) << std::endl;

И получить 100 цифр вывода:

9.8226639647960475701733500979688283399590376257717309069410413822165082248153638454147004236848917775e-01

В качестве бонуса мы теперь можем называть функцию не только шаблонами выражений, но и другими смешанными типами: например<float>и<double>или<int>и<double>, и в каждом случае будет вычисляться правильный тип возврата.

Обратите внимание, что хотя в этом случае нам не нужно было менять тело функции, в общем случае любая функция, подобная этой, которая создает локальные переменные внутри, должна была бы использовать<promote_args>для определения типа этих переменных, например:

template <class Float1, class Float2>
typename boost::math::tools::promote_args<Float1, Float2>::type
   JEL5(Float1 v, Float2 z)
{
   using std::pow;
   typedef typename boost::math::tools::promote_args<Float1, Float2>::type variable_type;
   variable_type t = pow(z / 2, v);
   return boost::math::tgamma(v + 1) * boost::math::cyl_bessel_j(v, z) / t;
}

PrevUpHomeNext

Статья Defining a Special Function. раздела Chapter 1. Boost.Multiprecision Examples может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Examples ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 04:46:55/0.0046570301055908/0