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

Boost Interval Arithmetic Library

Boost , ,

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

Interval Arithmetic Library

Содержание этой страницы:
Введение
Синопсис
Класс шаблонов<interval>
Операции и функции
Интервальная библиотека поддержки
Другие страницы, связанные с этой страницей:
Политика округления
Политика проверки
Манипулирование политикой
Сравнения
Основные требования к типу номера
Выбор собственного интервального типа
Тестовые и примерные программы
Включение заголовков
Некоторые элементы в списке тодо

Introduction and Overview

Как следует из названия, эта библиотека предназначена для манипулирования математическими интервалами. Он состоит из одного заголовка<boost/numeric/interval.hpp>и, в основном, типа, который может использоваться в качестве<interval<T>>. Фактически, этот шаблон интервала объявляется как<interval<T,Policies>>, где<Policies>является классом политики, который контролирует различные поведения класса интервала;<interval<T>>просто выбирает политику по умолчанию для типа<T>.

Предупреждение!Гарантированная интервальная арифметика для нативного формата с плавающей запятой поддерживается не на каждой комбинации процессора, операционной системы и компилятора. Это список систем, которые, как известно, работают правильно при использовании<interval<float>>и<interval<double>>с базовыми арифметическими операторами.

  • x86-подобное оборудование поддерживается библиотекой с GCC, Visual C++ ≥ 7.1, компилятором Intel (≥ 8 на Windows), CodeWarrior (≥ 9), при условии, что традиционный блок с плавающей запятой x87 используется для вычислений с плавающей запятой (без поддержки-mfpmath=sse2).
  • Оборудование Sparc поддерживается GCC и Sun.
  • Аппаратное обеспечение PowerPC поддерживается GCC и CodeWarrior, когда вычисления с плавающей запятой не выполняются с блоком Altivec.
  • Аппаратное обеспечение Alpha поддерживается GCC, за исключением, возможно, квадратного корня. Варианты-mfp-rounding-mode=d -mieeeнеобходимо использовать.

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

Interval Arithmetic

Интервал — это пара чисел, которая представляет все числа между этими двумя. (Интервалы считаются закрытыми, поэтому границы включены.) Целью этой библиотеки является расширение обычных арифметических функций до интервалов. Эти интервалы будут записаныa,bдля представления всех чисел междуaиb(включено).aиbмогут быть бесконечными (но они не могут быть одинаковыми бесконечными) иab.

Основным свойством интервальной арифметики являетсясвойство включения:

``if f is a function on a set of numbers, f can be extended to a new function defined on intervals. This new function f takes one interval argument and returns an interval result such as: ∀ x ∈ [a,b], f(x) ∈ f([a,b]).''

Такое свойство не ограничивается функциями только с одним аргументом. По возможности, интервальный результат должен быть наименьшим, способным удовлетворить свойство (это не очень полезно, если новые функции всегда отвечают).

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

Другой распространенной причиной использования интервальной арифметики является то, что компьютер не дает точных результатов: используя интервалы, можно количественно оценить распространение ошибок округления. Этот подход часто используется в численных вычислениях. Например, предположим, что компьютер хранит числа с десятью десятичными значащими цифрами. На вопрос 1 + 1Е-100 - 1, компьютер ответит 0, хотя правильный ответ будет 1Е-100. С помощью интервальной арифметики компьютер ответит [0,1Е-9]. Это довольно большой интервал для такого небольшого результата, но точность теперь известна, без необходимости вычислять распространение ошибок.

Numbers, rounding, and exceptional behavior

Типбазового числаявляется типом, который удерживает границы интервала. Для того чтобы успешно использовать интервальную арифметику, тип числа базы должен представлять некоторыехарактеристики. Во-первых, из-за определения интервала базовые числа должны быть полностью упорядочены, поэтому, например,<complex<T>>не может использоваться в качестве типа базового числа для интервалов. Математические функции для типа базового числа также должны быть совместимы с полным порядком (например, если x>y и z>t, то он также должен содержать, что x+z>y+t), поэтому типы модуля также не могут использоваться.

Во-вторых, вычисления должны быть точными или предоставлять некоторые методы округления (например, в сторону минус или плюс бесконечности), если мы хотим гарантировать свойство включения. Обратите внимание, что мы также можем четко указать отсутствие округления, например, если тип числа базы точен, то есть результат математической операции всегда вычисляется и представляется без потери точности. Если тип номера не является точным, мы все равно можем четко указать отсутствие округления, что означает, что свойство включения больше не гарантируется.

Наконец, поскольку всегда возможна большая потеря точности, некоторые числа должны представлять бесконечности или должно быть определено исключительное поведение. То же самое происходит и с NaNNot a Number.

Учитывая все это, можно ограничить аргумент шаблона T шаблона класса<interval>типами с плавающей точкой<float>,<double>и<long double>, как определено стандартом IEEE-754. Действительно, если арифметика интервала предназначена для замены арифметики, предоставляемой блоком с плавающей запятой процессора, эти типы являются лучшим выбором. Однако, в отличие от<std::complex>, мы не хотим ограничивать<T>этими типами. Вот почему мы позволяем, чтобы эти две политики (округление и проверка) обеспечивали исключительное поведение. Тем не менее, мы предоставляем высоко оптимизированные специализации для округления и проверки классов для вышеупомянутых типов плавающих точек.

Operations and functions

Несложно определить элементарные арифметические операции на интервалах, руководствуясь свойством включения. Например, если [a,b] и [c,d] являются интервалами, [a,b]+[c,d] можно вычислить, взяв наименьший интервал, который содержит все числа x+y для x в [a,b] и y в [c,d]; в этом случае будет достаточно округления a+c вниз и b+d вверх. Аналогичным образом определяются другие операторы и функции (см. их определения ниже).

Comparisons

Также можно выделить несколько операторов сравнения. При наличии двух интервалов получается трехсостояние булевого типа {ложное,истинное, неопределенное}. Ответыложныеиистинныелегко манипулировать, поскольку они могут быть непосредственно отображены на булевойистинныйиложный. Но ответнеопределен, поскольку операторы сравнения должны быть булевыми функциями. Итак, что же делать, чтобы получить булевы ответы?

Одно из решений состоит в принятии решения о принятии исключительного поведения, такого как неудавшееся утверждение или введение исключения. В этом случае исключительное поведение запускается, когда результат неопределён.

Другое решение состоит в том, чтобы сопоставитьнеопределенноевсегда сложным,или всегда систинным. Если выбранложный, сравнение будет называтьсянекоторый; действительно, результатa,b]<c,d] будетистинный, если и только если: ∀xa,byc,d,x<118] y. Еслиистинновыбрано, сравнение будет называтьсявозможным; действительно, результатa,b]<c,d] будетистинным, если и только если: ∃xa,byc,d,x<118] y.

Поскольку любое из этих решений имеет четко определенную семантику, не ясно, следует ли применять их. По этой причине поведение по умолчанию состоит в том, чтобы имитировать реальные сравнения, бросая исключение в неопределенный случай. Другие модели поведения могут быть выбраны с использованием конкретного пространства имен сравнения. Существует также множество явно названных функций сравнения. См.сравнениястраницы для более подробной информации.

Overview of the library, and usage

Эта библиотека обеспечивает два совершенно разных уровня использования. Один из них заключается в использовании базового шаблона класса<interval<T>>без указания политики. Для этого нужно только знать и понимать концепции, разработанные выше, и содержание расширения пространства имен. В дополнение к классу<interval<T>>этот уровень использования обеспечивает арифметические операторы<+>,<->,<*>,</>,<square>,<sqrt>,<sqrt>,<sin>,<sin>,<tan>,<tan>,<asin>,<atan>,<cosh>,<cosh>,<asinh>,<acosh>,<acosh>,<atanh>,<atan>,<>>,<>=>,<==>,<!=>,<std::max>, а также несколько интервальных функций<lower>,<upper>,<width>,<median>,<singleton>,<equal>,<equal>,<zero_in>,<subset>,<overlap>,<intersect>,<hull>,<bisect>.

Для некоторых функций, которые принимают несколько параметров типа<interval<T>>, все комбинации типов аргументов<T>и<interval<T>>, которые содержат по меньшей мере один<interval<T>>, рассматриваются во избежание преобразования из аргументов типа<T>в однотон типа<interval<T>>. Это делается по соображениям эффективности (тот факт, что аргумент является одиночным, иногда делает некоторые тесты ненужными).

Несколько более продвинутое использование этой библиотеки состоит в том, чтобы вручную выбирать политики<Rounding>и<Checking>и передавать их<interval<T, Policies>>с помощью<Policies := boost::numeric::interval_lib::policies<Rounding,Checking>>. Соответствующие политики могут быть сфабрикованы с использованием различных классов, представленных в пространстве имен<boost::numeric::interval_lib>, как подробно описано в разделеБиблиотека Интервальной поддержки. Также можно выбрать схему сравнения, перегрузив операторов через пространства имен.

Synopsis

namespace boost {
namespace numeric {
namespace interval_lib {
/* this declaration is necessary for the declaration of interval */
template <class T> struct default_policies;
/* ... ; the full synopsis of namespace interval_lib can be found here */
} // namespace interval_lib
/* template interval_policies; class definition can be found here */
template<class Rounding, class Checking>
struct interval_policies;
/* template class interval; class definition can be found here */
template<class T, class Policies = typename interval_lib::default_policies<T>::type > class interval;
/* arithmetic operators involving intervals */
template <class T, class Policies>  interval<T, Policies> operator+(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> operator-(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> operator+(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator+(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> operator+(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator-(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator-(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> operator-(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator*(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator*(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> operator*(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator/(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> operator/(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> operator/(const T& r, const interval<T, Policies>& x);
/* algebraic functions: sqrt, abs, square, pow, nth_root */
template <class T, class Policies>  interval<T, Policies> abs(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> sqrt(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> square(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> pow(const interval<T, Policies>& x, int y);
template <class T, class Policies>  interval<T, Policies> nth_root(const interval<T, Policies>& x, int y);
/* transcendental functions: exp, log */
template <class T, class Policies>  interval<T, Policies> exp(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> log(const interval<T, Policies>& x);
/* fmod, for trigonometric function argument reduction (see below) */
template <class T, class Policies>  interval<T, Policies> fmod(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> fmod(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> fmod(const T& x, const interval<T, Policies>& y);
/* trigonometric functions */
template <class T, class Policies>  interval<T, Policies> sin(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> cos(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> tan(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> asin(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> acos(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> atan(const interval<T, Policies>& x);
/* hyperbolic trigonometric functions */
template <class T, class Policies>  interval<T, Policies> sinh(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> cosh(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> tanh(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> asinh(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> acosh(const interval<T, Policies>& x);
template <class T, class Policies>  interval<T, Policies> atanh(const interval<T, Policies>& x);
/* min, max external functions (NOT std::min/max, see below) */
template <class T, class Policies>  interval<T, Policies> max(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> max(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> max(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> min(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> min(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> min(const T& x, const interval<T, Policies>& y);
/* bounds-related interval functions */
template <class T, class Policies>  T lower(const interval<T, Policies>& x);
template <class T, class Policies>  T upper(const interval<T, Policies>& x);
template <class T, class Policies>  T width(const interval<T, Policies>& x);
template <class T, class Policies>  T median(const interval<T, Policies>& x);
template <class T, class Policies>  T norm(const interval<T, Policies>& x);
/* bounds-related interval functions */
template <class T, class Policies>  bool empty(const interval<T, Policies>& b);
template <class T, class Policies>  bool singleton(const interval<T, Policies>& x);
template <class T, class Policies>  bool equal(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool in(const T& r, const interval<T, Policies>& b);
template <class T, class Policies>  bool zero_in(const interval<T, Policies>& b);
template <class T, class Policies>  bool subset(const interval<T, Policies>& a, const interval<T, Policies>& b);
template <class T, class Policies>  bool proper_subset(const interval<T, Policies>& a, const interval<T, Policies>& b);
template <class T, class Policies>  bool overlap(const interval<T, Policies>& x, const interval<T, Policies>& y);
/* set manipulation interval functions */
template <class T, class Policies>  interval<T, Policies> intersect(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> hull(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> hull(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  interval<T, Policies> hull(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  interval<T, Policies> hull(const T& x, const T& y);
template <class T, class Policies>  std::pair<interval<T, Policies>, interval<T, Policies> > bisect(const interval<T, Policies>& x);
/* interval comparison operators */
template<class T, class Policies>  bool operator<(const interval<T, Policies>& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator<(const interval<T, Policies>& x, const T& y);
template<class T, class Policies>  bool operator<(const T& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator<=(const interval<T, Policies>& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator<=(const interval<T, Policies>& x, const T& y);
template<class T, class Policies>  bool operator<=(const T& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator>(const interval<T, Policies>& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator>(const interval<T, Policies>& x, const T& y);
template<class T, class Policies>  bool operator>(const T& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator>=(const interval<T, Policies>& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator>=(const interval<T, Policies>& x, const T& y);
template<class T, class Policies>  bool operator>=(const T& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator==(const interval<T, Policies>& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator==(const interval<T, Policies>& x, const T& y);
template<class T, class Policies>  bool operator==(const T& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator!=(const interval<T, Policies>& x, const interval<T, Policies>& y);
template<class T, class Policies>  bool operator!=(const interval<T, Policies>& x, const T& y);
template<class T, class Policies>  bool operator!=(const T& x, const interval<T, Policies>& y);
namespace interval_lib {
template<class T, class Policies>  interval<T, Policies> division_part1(const interval<T, Policies>& x, const interval<T, Policies& y, bool& b);
template<class T, class Policies>  interval<T, Policies> division_part2(const interval<T, Policies>& x, const interval<T, Policies& y, bool b = true);
template<class T, class Policies>  interval<T, Policies> multiplicative_inverse(const interval<T, Policies>& x);
template<class I>  I add(const typename I::base_type& x, const typename I::base_type& y);
template<class I>  I sub(const typename I::base_type& x, const typename I::base_type& y);
template<class I>  I mul(const typename I::base_type& x, const typename I::base_type& y);
template<class I>  I div(const typename I::base_type& x, const typename I::base_type& y);
} // namespace interval_lib
} // namespace numeric
} // namespace boost

Template class interval

The public interface of the template class interval itself is kept at a simplest minimum:
template <class T, class Policies = typename interval_lib::default_policies<T>::type>
class interval
{
  public:
  typedef T base_type;
  typedef Policies traits_type;
  interval();
  interval(T const &v);
  template<class T1> interval(T1 const &v);
  interval(T const &l, T const &u);
  template<class T1, class T2> interval(T1 const &l, T2 const &u);
  interval(interval<T, Policies> const &r);
  template<class Policies1> interval(interval<T, Policies1> const &r);
  template<class T1, class Policies1> interval(interval<T1, Policies1> const &r);
  interval &operator=(T const &v);
  template<class T1> interval &operator=(T1 const &v);
  interval &operator=(interval<T, Policies> const &r);
  template<class Policies1> interval &operator=(interval<T, Policies1> const &r);
  template<class T1, class Policies1> interval &operator=(interval<T1, Policies1> const &r);
  void assign(T const &l, T const &u);
  T const &lower() const;
  T const &upper() const;
  static interval empty();
  static interval whole();
  static interval hull(T const &x, T const &y);
  interval& operator+= (T const &r);
  interval& operator-= (T const &r);
  interval& operator*= (T const &r);
  interval& operator/= (T const &r);
  interval& operator+= (interval const &r);
  interval& operator-= (interval const &r);
  interval& operator*= (interval const &r);
  interval& operator/= (interval const &r);
};

Конструкторы создают интервал, заключающий их аргументы. Если есть два аргумента, первый считается левым, а второй — правым. Следовательно, аргументы необходимо упорядочить. Если свойство !(l<=u) не соблюдается, то для создания пустого интервала будет использована политика проверки. Если аргумент не приводится, то созданный интервал равен нулю синглтона.

Если тип аргументов совпадает с типом базового числа, значения непосредственно используются для границ. Если это не тот же тип, библиотека будет использовать политику округления для преобразования аргументов<conv_down>и<conv_up>и создания замкнутого интервала. Когда аргумент представляет собой интервал с другой политикой, входной интервал проверяется, чтобы правильно распространять его пустоту (если он пуст).

Операторы присваивания ведут себя аналогично, за исключением того, что они явно принимают только один аргумент. Существует также функция<assign>для того, чтобы непосредственно изменять границы интервала. Он ведет себя как конструкторы двух аргументов, если границы не упорядочены. Не существует функции назначения, которая непосредственно принимает интервал или только одно число в качестве параметра; просто используйте операторов назначения в таком случае.

Тип границ и политики интервального типа определяют набор значений, которые содержат интервалы. Например, с политиками по умолчанию интервалы являются подмножествами набора реальных чисел. Статические функции<empty>и<whole>производят интервалы/подмножества, которые являются соответственно пустым подмножеством и целым множеством. Они являются статическими функциями, а не глобальными функциями, потому что они не могут угадать их типы возврата. Аналогично для<hull>.<empty>и<whole>включите политику проверки, чтобы получить границы результирующих интервалов.

Operations and Functions

Некоторые из следующих функций ожидают, что<min>и<max>будут определены для базового типа. Это единственные требования к классу<interval>(но политики могут иметь и другие требования).

Operators + - * / += -= *= /=

Основными операциями являются унарный минус и двоичный<+><-><*></>. Унарный минус берет интервал и возвращает интервал. Бинарные операции занимают два интервала, или один интервал и число, и возвращают интервал. Если аргумент является числом, а не интервалом, можно ожидать, что результат будет таким же, как если бы число было сначала преобразовано в интервал. Это свойство будет справедливо для всех следующих функций и операторов.

Есть также некоторые операторы присваивания<+=><-=><*=></=>. Нечего и говорить:<x op= y>эквивалентно<x = x op y>. Если во время вычислений выбрасывается исключение, значение l не изменяется (но оно может быть повреждено, если исключение бросается базовым типом во время назначения).

Операторы</>и</=>попытаются произвести пустой интервал, если знаменатель точно равен нулю. Если знаменатель содержит ноль (но не только ноль), результат будет наименьшим интервалом, содержащим множество результатов деления; таким образом, одна из его границ будет бесконечной, но она не может быть целым интервалом.

lower upper median width norm

<lower>,<upper>,<median>соответственно вычисляют нижнюю границу, верхнюю границу и среднее число интервала<(lower+upper)/2>, округленного до ближайшего.<width>вычисляет ширину интервала<upper-lower>, округленного в сторону плюс бесконечность.<norm>вычисляет верхнюю границу интервала в абсолютном значении; это математическая норма (отсюда и название), аналогичная абсолютному значению для действительных чисел.

min max abs square pow nth_root division_part? multiplicative_inverse

Также определены функции<min>,<max>и<abs>. Пожалуйста, не путайте их с функциями, определенными в стандартной библиотеке (ака<a<b?a:b>,<a>b?a:b>,<a<0?-a:a>). Эти функции совместимы с элементарным свойством интервальной арифметики. Например, max [a,b], [c,d] = {max [x,y], так чтоxв [a,bиув [c,d]]. Они определены не в пространстве имен<std>, а в пространстве имен ускорения, чтобы избежать конфликта с другими определениями.

Функция<square>довольно специфическая. Как и следовало ожидать от его названия, он вычисляет квадрат своего аргумента. Причина, по которой эта функция предоставлена:<square(x)>не<x*x>, а только подмножество, когда<x>содержит ноль. Например, [-2,2]*[-2,2] = [-4,4], но [-2,2]² = [0,4]; результатом является меньший интервал. Следовательно,<square(x)>следует использовать вместо<x*x>из-за его лучшей точности и небольшого улучшения производительности.

Что касается<square>,<pow>обеспечивает эффективный и более точный способ вычисления целочисленной мощности интервала. Обратите внимание: когда мощность равна 0 и интервал не пуст, результат равен 1, даже если входной интервал содержит 0.<nth_root>вычисляет целочисленный корень интервала<nth_root(pow(x,k),k)>заключает<x>или<abs(x)>в зависимости от того, является ли<k>нечетным или четным. Поведение<nth_root>не определено, если целочисленный аргумент не является положительным.<multiplicative_inverse>вычисляет<1/x>.

Функции<division_part1>и<division_part2>полезны, когда пользователь ожидает, что разделение вернет разъединенные интервалы, если это необходимо. Например, самое узкое замкнутое множество, содержащее [2,3] / [-2,1], не является ]-∞,∞[, но объединение ]-∞,-1] и [2,∞[. Когда результат деления представлен только одним интервалом,<division_part1>возвращает этот интервал и устанавливает булеву ссылку на<false>. Однако если результат требует двух интервалов,<division_part1>возвращает отрицательную часть и устанавливает булеву ссылку на<true>; теперь для получения положительной части требуется вызов на<division_part2>. Эта вторая функция может принимать булеву, возвращенную первой функцией, в качестве последнего аргумента. Если это значение не дано, его значение считается истинным, и поведение функции не определено, если разделение не производит второй интервал.

intersect hull overlap in zero_in subset proper_subset empty singleton equal

<intersect>вычисляет множество пересечений двух замкнутых множеств,<hull>вычисляет наименьший интервал, который содержит два параметра; эти параметры могут быть числами или интервалами. Если один из аргументов является недействительным числом или пустым интервалом, функция будет использовать другой аргумент только для вычисления полученного интервала (если это разрешено политикой проверки).

Функции союза не существует, так как объединение двух интервалов не является интервалом, если они не пересекаются. Если они пересекаются, функция<hull>вычисляет союз.

Функция<overlap>проверяет, имеют ли два интервала некоторое общее подмножество.<in>тестирует, если число находится в интервале;<zero_in>является вариантом, который тестирует, если ноль находится в интервале.<subset>испытания, если первый интервал является подмножеством второго; и<proper_subset>испытания, если он является надлежащим подмножеством.<empty>и<singleton>тестируют, является ли интервал пустым или является одиночным. Наконец,<equal>тесты, если два интервала равны.

sqrt log exp sin cos tan asin acos atan sinh cosh tanh asinh acosh atanh fmod

Определены также функции<sqrt>,<log>,<exp>,<sin>,<cos>,<tan>,<asin>,<acos>,<atan>,<sinh>,<cosh>,<tanh>,<asinh>,<acosh>,<atanh>. Нечего и говорить: эти функции расширяют традиционные функции до интервалов и уважают основное свойство интервальной арифметики. Они используют политикупроверкидля получения пустых интервалов, когда входной интервал находится строго за пределами области функции.

Функция<fmod(interval x, interval y)>ожидает, что нижняя граница<y>будет строго положительной и возвращает интервал<z>, такой как<0 <= z.lower() < y.upper()>и такой как<z>, является надмножеством<x-n*y>(с<n>, являющимся целым числом). Таким образом, если два аргумента являются положительными одиночками, эта функция<fmod(interval, interval)>будет вести себя как традиционная функция<fmod(double, double)>.

Обратите внимание, что<fmod>не учитывает свойство включения арифметического интервала. Например, результат<fmod>([13,17], [7,8]) должен быть [0,8] (поскольку он должен содержать [0,3] и [5,8]). Но этот ответ не очень полезен, когда целью является ограничение интервала для вычисления периодической функции. Вот почему<fmod>ответит [5,10].

add sub mul div

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

Constants

Некоторые константы скрыты в пространстве имен<boost::numeric::interval_lib>. Они должны быть явно шаблонизированы по типу интервала. Функции<pi<I>()>,<pi_half<I>()>и<pi_twice<I>()>возвращают объект интервального типа<I>. Их соответствующие значения π, π/2 и 2π.

Exception throwing

Класс интервалов и все функции, определенные вокруг этого класса, никогда не делают исключений сами по себе. Однако это не значит, что операция никогда не станет исключением. Рассмотрим, например, конструктор копий. Как объяснялось ранее, это конструктор копий по умолчанию, созданный компилятором. Таким образом, он не будет выбрасывать исключение, если конструктор-копировщик базового типа не выбрасывает исключение.

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

Interval Support Library

Библиотека поддержки интервалов состоит из набора классов, которые могут быть использованы и объединены для изготовления почти различных часто необходимых интервальных политик. В отличие от основных классов и функций, которые используются в сочетании с<interval<T>>(и политиками по умолчанию в качестве неявного второго параметра шаблона в этом типе), которые принадлежат просто пространству имен<boost>, эти компоненты принадлежат пространству имен<boost::numeric::interval_lib>.

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

Synopsis

namespace boost {
namespace numeric {
namespace interval_lib {
/* built-in rounding policy and its specializations */
template <class T>  struct rounded_math;
template <>         struct rounded_math<float>;
template <>         struct rounded_math<double>;
template <>         struct rounded_math<long double>;
/* built-in rounding construction blocks */
template <class T>  struct rounding_control;
template <class T, class Rounding = rounding_control<T> >  struct rounded_arith_exact;
template <class T, class Rounding = rounding_control<T> >  struct rounded_arith_std;
template <class T, class Rounding = rounding_control<T> >  struct rounded_arith_opp;
template <class T, class Rounding>  struct rounded_transc_dummy;
template <class T, class Rounding = rounded_arith_exact<T> >  struct rounded_transc_exact;
template <class T, class Rounding = rounded_arith_std  <T> >  struct rounded_transc_std;
template <class T, class Rounding = rounded_arith_opp  <T> >  struct rounded_transc_opp;
template <class Rounding> struct save_state;
template <class Rounding> struct save_state_nothing;
/* built-in checking policies */
template <class T> struct checking_base;
template <class T, class Checking = checking_base<T>, class Exception = exception_create_empty>   struct checking_no_empty;
template <class T, class Checking = checking_base<T> >                                            struct checking_no_nan;
template <class T, class Checking = checking_base<T>, class Exception = exception_invalid_number> struct checking_catch_nan;
template <class T> struct checking_strict;
/* some metaprogramming to manipulate interval policies */
template <class Rounding, class Checking> struct policies;
template <class OldInterval, class NewRounding> struct change_rounding;
template <class OldInterval, class NewChecking> struct change_checking;
template <class OldInterval> struct unprotect;
/* constants, need to be explicitly templated */
template<class I> I pi();
template<class I> I pi_half();
template<class I> I pi_twice();
/* interval explicit comparison functions:
 * the mode can be cer=certainly or pos=possibly,
 * the function lt=less_than, gt=greater_than, le=less_than_or_equal_to, ge=greater_than_or_equal_to
 *   eq=equal_to, ne= not_equal_to */
template <class T, class Policies>  bool cerlt(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerlt(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool cerlt(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerle(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerle(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool cerle(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cergt(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cergt(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool cergt(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerge(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerge(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool cerge(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cereq(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cereq(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool cereq(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerne(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool cerne(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool cerne(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool poslt(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool poslt(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool poslt(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posle(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posle(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool posle(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posgt(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posgt(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool posgt(const T& x, const interval<T, Policies> & y);
template <class T, class Policies>  bool posge(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posge(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool posge(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool poseq(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool poseq(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool poseq(const T& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posne(const interval<T, Policies>& x, const interval<T, Policies>& y);
template <class T, class Policies>  bool posne(const interval<T, Policies>& x, const T& y);
template <class T, class Policies>  bool posne(const T& x, const interval<T, Policies>& y);
/* comparison namespaces */
namespace compare {
  namespace certain;
  namespace possible;
  namespace lexicographic;
  namespace set;
  namespace tribool;
} // namespace compare
} // namespace interval_lib
} // namespace numeric
} // namespace boost

Каждый компонент библиотеки поддержки интервала подробно описан на своей странице.

Common Pitfalls and Dangers

Comparisons

Одной из самых больших проблем, вероятно, является правильное использование функций сравнения и операторов. Во-первых, функции и операторы не пытаются узнать, являются ли два интервала одним и тем же математическим объектом. Таким образом, если используемое сравнение является «определенным», то<x != x>всегда верно, если<x>не является интервалом одинарности; и та же проблема возникает с<cereq>и<cerne>.

Другая вводящая в заблуждение интерпретация сравнения: вы не всегда можете ожидать, что [a,b]< [c,d] будет ! ([a,b] >= [c,d]), поскольку сравнение не обязательно является полным. Равенство и меньшее сравнение следует рассматривать как два различных реляционных оператора. Однако операторы сравнения по умолчанию уважают это свойство, поскольку они бросают исключение всякий раз, когда [a,b] и [c,d] пересекаются.

Interval values and references

Эта проблема является следствием предыдущей проблемы<x != x>. Все функции библиотеки учитывают только значение интервала, а не ссылку на интервал. В частности, не следует ожидать (если<x>не является синглоном) равенства следующих значений:<x/x>и 1,<x*x>и<square(x)>,<x-x>и 0 и т.д. Таким образом, основной причиной широких интервалов является то, что интервальная арифметика не идентифицирует различные случаи одной и той же переменной. Таким образом, когда это возможно, пользователь должен переписать формулы, чтобы исключить множественные случаи одной и той же переменной. Например,<square(x)-2*x>гораздо менее точен, чем<square(x-1)-1>.

Unprotected rounding

Как объясняется вэтом разделе, хороший способ ускорить вычисления, когда базовый тип является основным типом с плавающей точкой, заключается в том, чтобы не защищать интервалы в горячих точках алгоритма. Этот метод является безопасным и действительно улучшением для интервальных вычислений. Но помните, что любая базовая операция с плавающей запятой, выполняемая внутри блоков незащищенности, вероятно, будет иметь неопределенное поведение (но только для текущего потока). И не забудьте создать округлый объект, как объясняется впримере.

Rationale

Цель этой библиотеки состоит в том, чтобы обеспечить эффективный и обобщенный способ работы с интервальной арифметикой с помощью шаблонизированного класса<boost::numeric::interval>. Большим спором, для которого мы приводим обоснование, является формат этого шаблона класса.

Было бы легче обеспечить интервал класса, базовый тип которого является двойным. Или следовать<std::complex>и разрешать только специализации для<float>,<double>и<long double>. Мы решили не делать этого, чтобы разрешить интервалы на пользовательских типах, например, типах библиотек с фиксированной точностью (MPFR и т. д.), рациональных числах и так далее.

Проектирование.Хотя было заманчиво сделать его классовым шаблоном только с одним шаблонным аргументом, разнообразие применений для интервальной арифметики практически заставило нас использовать политику. Поведение этого класса может быть определено двумя политиками. Эти политики упакованы в единый класс политик, а не делают<interval>с тремя шаблонными параметрами. Это как для удобства использования (класс политики может быть выбран по умолчанию), так и для удобства чтения.

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

Мы могли бы предвидеть ситуации, когда любое сочетание этих стратегий было бы уместным. Более того, мы хотели дать возможность пользователю библиотеки повторно использовать шаблон класса<interval>, одновременно выбирая его собственное поведение. См. этустраницудля некоторых примеров.

Политика округления.Библиотека обеспечивает специализированные реализации политики округления для примитивных типов плавающих и двойных. Чтобы эти реализации были правильными и быстрыми, библиотеке нужно много работать с режимами округления. Некоторые процессоры непосредственно обрабатываются, а некоторые механизмы предоставляются для ускорения вычислений. Кажется, что это тяжелая и опасная оптимизация для получения всего нескольких компьютерных циклов; но на самом деле коэффициент ускорения может легко пройти 2 или 3 в зависимости от компьютера. Более того, эти оптимизации никак не влияют на интерфейс (с выбранным дизайном все можно добавить по специализации или путем прохождения различных параметров шаблона).

Пред/Сукц.В предыдущей версии были представлены две функции<pred>и<succ>, с различными выводами, такими как<widen>. Цель состояла в том, чтобы увеличить интервал на один ulp (как можно меньше), например, чтобы обеспечить свойство включения. Поскольку мы сделали интервал шаблоном T, мы не могли определитьulpдля случайного параметра. В свою очередь, политика округления позволяет полностью исключить использование ulp, одновременно увеличивая интервалы (если результатом является репрезентативный синглтон, нет смысла расширять интервал). Мы решили отказаться от этих функций.

Специализация<std::less>Поскольку оператор<<>зависит от локально выбранного пользователем пространства имен сравнения, правильно специализироваться<std::less>невозможно. Таким образом, вы должны явно предоставить такой класс всем алгоритмам и шаблонам, которые могут его потребовать (например,<std::map>).

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

Смешанные операции с целыми числами.При использовании и повторном использовании шаблонных кодов часто встречаются такие операции, как<2*x>. Однако библиотека не предоставляет их по умолчанию, потому что преобразование из<int>в тип базового номера не всегда правильно (подумайте о преобразовании из 32-битного целого числа в одно точное число с плавающей запятой). Таким образом, функции были помещены в отдельный заголовок, и пользователь должен включить их явно, если он хочет извлечь выгоду из этих смешанных операторов. Кроме того, нет смешанных операторов сравнения из-за технического способа их определения.

Функции интервализации.Все функции, определенные библиотекой, очевидно, знают, что они манипулируют интервалами и делают это соответственно общим арифметическим принципам интервала. Следовательно, они могут иметь иное поведение, чем то, которое обычно встречается с функциями, не зависящими от интервала. Например,<max>определяется каноническим расширением множества и результат не всегда является одним из двух аргументов (если интервалы не перекрываются, то результат является одним из двух интервалов).

Это поведение отличается от<std::max>, которое возвращает ссылку на один из своих аргументов. Поэтому, если пользователь ожидает, что ссылка будет возвращена, он должен использовать<std::max>, поскольку это именно то, что делает эта функция. Обратите внимание, что<std::max>будет делать исключение, когда интервалы перекрываются. Это поведение не предшествует описанному стандартом C++, поскольку аргументы не являются «эквивалентными» и позволяет иметь эквивалентность между<a <= b>и<&b == &std::max(a,b)>(некоторые конкретные случаи могут быть определены реализацией). Однако он отличается от того, который описывается SGI, поскольку он не возвращает первый аргумент, даже если «ни один из них не больше другого».

History and Acknowledgments

Эта библиотека была в основном вдохновлена предыдущими работами Йенса Маурера. Некоторые рассуждения о его творчестве воспроизводятся здесь. Джереми Сик и Маартен Кейзер предоставили некоторое управление округлением для платформ MSVC и Sparc.

Guillaume Melquiond, Hervé Brönnimann и Sylvain Pion начали с библиотеки, оставленной Йенсом, и добавили дизайн политики. Гийом и Сильвен много работали над кодом, особенно над портированием и в основном настройкой режимов округления к различным архитектурам. Гийом сделал большую часть кодирования, в то время как Сильвен и Герв и Острый предоставили некоторые полезные комментарии для того, чтобы эта библиотека была написана. Hervé реорганизовал и написал главы документации, основанные на отличной отправной точке Гийома.

Этот материал частично основан на работе, поддержанной Национальным научным фондом NSF CAREER Grant CCR-0133599. Любые мнения, выводы и выводы или рекомендации, выраженные в этом материале, являются мнениями автора (ов) и не обязательно отражают взгляды Национального научного фонда (NSF).


Valid HTML 4.01 Transitional

Пересмотренный2006-12-252006-12-25[ORIG_END] -->

Copyright © 2002 Guillaume Melquiond, Sylvain Pion, Hervé Brönnimann, Polytechnic University
Copyright © 2003-2006 Гийом Мелкион, ENS Lyon

Распространяется в соответствии с Лицензией на программное обеспечение Boost, версия 1.0. (См. сопроводительный файлLICENSE_1_0.txtили копию на) http://www.boost.org/LICENSE_1_0.txt)

Статья Boost Interval Arithmetic Library раздела может быть полезна для разработчиков на c++ и boost.




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



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


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:34:55/0.041162967681885/1