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

Implementation

Boost , Math Toolkit 2.5.0 , Tutorial: How to Write a New Special Function

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

В этом разделе мы предоставим «рецепт» для добавления новой специальной функции в эту библиотеку, чтобы облегчить жизнь будущим авторам, желающим внести свой вклад. Мы предположим, что функция возвращает один результат с плавающей точкой и принимает два аргумента с плавающей точкой. Для изложения мы дадим функции имя<my_special>.

Обычно реализация такой функции разбивается на два слоя — общедоступный пользовательский слой и внутренний уровень реализации, выполняющий фактическую работу. Слой реализации объявляется внутри пространства имен<detail>и имеет простую подпись:

namespace boost { namespace math { namespace detail {
template <class T, class Policy>
T my_special_imp(const T& a, const T&b, const Policy& pol)
{
   /* Implementation goes here */
}
}}} // namespaces

Мы вернемся к тому, что может войти в реализацию позже, но сначала давайте посмотрим на пользовательский уровень. Это состоит из двух перегрузок функции, с аргументомПолитикаи без него:

namespace boost{ namespace math{
template <class T, class U>
typename tools::promote_args<T, U>::type my_special(const T& a, const U& b);
template <class T, class U, class Policy>
typename tools::promote_args<T, U>::type my_special(const T& a, const U& b, const Policy& pol);
}} // namespaces

Обратите внимание, что каждый аргумент имеет различный тип шаблона - это позволяет использовать аргументы смешанного типа - тип возврата вычисляется из класса признаков и является «общим типом» всех аргументов после того, как любые целочисленные аргументы были продвинуты на тип<double>.

Осуществление неполитической перегрузки тривиально:

namespace boost{ namespace math{
template <class T, class U>
inline typename tools::promote_args<T, U>::type my_special(const T& a, const U& b)
{
   // Simply forward with a default policy:
   return my_special(a, b, policies::policy<>();
}
}} // namespaces

Реализация другой перегрузки несколько сложнее, так как есть некоторое метапрограммирование, но с точки зрения времени выполнения все еще является функцией пересылки одной строки. Вот комментарии, объясняющие, что делает каждая строка:

namespace boost{ namespace math{
template <class T, class U, class Policy>
inline typename tools::promote_args<T, U>::type my_special(const T& a, const U& b, const Policy& pol)
{
   //
   // We've found some standard library functions to misbehave if any FPU exception flags
   // are set prior to their call, this code will clear those flags, then reset them
   // on exit:
   //
   BOOST_FPU_EXCEPTION_GUARD
   //
   // The type of the result - the common type of T and U after
   // any integer types have been promoted to double:
   //
   typedef typename tools::promote_args<T, U>::type result_type;
   //
   // The type used for the calculation.  This may be a wider type than
   // the result in order to ensure full precision:
   //
   typedef typename policies::evaluation<result_type, Policy>::type value_type;
   //
   // The type of the policy to forward to the actual implementation.
   // We disable promotion of float and double as that's [possibly]
   // happened already in the line above.  Also reset to the default
   // any policies we don't use (reduces code bloat if we're called
   // multiple times with differing policies we don't actually use).
   // Also normalise the type, again to reduce code bloat in case we're
   // called multiple times with functionally identical policies that happen
   // to be different types.
   //
   typedef typename policies::normalise<
      Policy,
      policies::promote_float<false>,
      policies::promote_double<false>,
      policies::discrete_quantile<>,
      policies::assert_undefined<> >::type forwarding_policy;
   //
   // Whew.  Now we can make the actual call to the implementation.
   // Arguments are explicitly cast to the evaluation type, and the result
   // passed through checked_narrowing_cast which handles things like overflow
   // according to the policy passed:
   //
   return policies::checked_narrowing_cast<result_type, forwarding_policy>(
         detail::my_special_imp(
               static_cast<value_type>(a),
               static_cast<value_type>(x),
               forwarding_policy()),
         "boost::math::my_special<%1%>(%1%, %1%)");
}
}} // namespaces

Сейчас мы почти на месте, нам просто нужно прояснить детали уровня реализации:

namespace boost { namespace math { namespace detail {
template <class T, class Policy>
T my_special_imp(const T& a, const T&b, const Policy& pol)
{
   /* Implementation goes here */
}
}}} // namespaces

Следующие руководящие принципы указывают, что (кроме базовой арифметики) может пойти в реализации:

  • Условия ошибки (например, плохие аргументы) должны обрабатываться путем вызова одного изобработчиков ошибок на основе политики..
  • Звонки в стандартные библиотечные функции должны быть сделаны неквалифицированными (это позволяет зависимому от аргумента поиску найти стандартные библиотечные функции для определяемых пользователем типов плавающих точек, таких как те изBoost.Multiprecision). Кроме того, макрос<BOOST_MATH_STD_USING>должен появиться в начале функции (заметьте, что после этого нет полуколона!), так что все математические функции в<namespace std>видны в текущем объеме.
  • Звонки на другие специальные функции должны выполняться в качестве полностью квалифицированных вызовов и включать в качестве последнего аргумента политический параметр, например<boost::math::tgamma(a,pol)>.
  • Там, где это возможно, для оценки последовательностей, непрерывных фракций, полиномов или нахождения корней следует использовать одну из функцийкотельной пластины. В любом случае, после любого итеративного метода следует проверить, что количество итераций не превысило максимум, указанный вПолитикетипа, и если оно действительно закончилось в результате превышения максимума, то следует вызвать соответствующего обработчика ошибок (см. существующий код для примеров).
  • Численные константы, такие как π и т.д., должны быть получены посредством вызовасоответствующей функции, например:<constants::pi<T>()>.
  • Там, где используются таблицы коэффициентов (например, для рациональных приближений), следует позаботиться о том, чтобы они были инициализированы при запуске программы для обеспечения безопасности потока при использовании определенных пользователем типов чисел. См., например, использование<erf_initializererf.hpp.

Вот некоторые другие полезные внутренние функции:

функция

значение

<policies::digits<T, Policy>()>

Возвращает число двоичных цифр в T (возможно, переопределяется политикой).

<policies::get_max_series_iterations<Policy>()>

Максимальное количество итераций для оценки серий.

<policies::get_max_root_iterations<Policy>()>

Максимальное количество итераций для поиска корней.

<polices::get_epsilon<T, Policy>()>

Эпсилон для типа Т, возможно, отменяемый Политикой.

<tools::digits<T>()>

Возвращает число двоичных цифр в T.

<tools::max_value<T>()>

эквивалентно<std::numeric_limits<T>::max()>

<tools::min_value<T>()>

эквивалентно<std::numeric_limits<T>::min()>

<tools::log_max_value<T>()>

Эквивалент натурального логарифма<std::numeric_limits<T>::max()>

<tools::log_min_value<T>()>

Эквивалент натурального логарифма<std::numeric_limits<T>::min()>

<tools::epsilon<T>()>

Эквивалентно<std::numeric_limits<T>::epsilon()>

.

<tools::root_epsilon<T>()>

Эквивалент квадратного корня<std::numeric_limits<T>::epsilon()>

.

<tools::forth_root_epsilon<T>()>

Эквивалентно четвертому корню<std::numeric_limits<T>::epsilon()>

.

PrevUpHomeNext

Статья Implementation раздела Math Toolkit 2.5.0 Tutorial: How to Write a New Special Function может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Tutorial: How to Write a New Special Function ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-07-05 03:18:21/0.0052509307861328/0