|
sigma
1.0.0
|
Implements affine arithmetic. More...
#include <affine.hpp>
Public Types | |
| using | size_type = std::size_t |
| Type used for indexing and offsets. | |
| using | value_t = ValueType |
| Type used for storing floating point values. | |
| using | error_term_t = std::shared_ptr<size_type> |
| Opaque type used to store error term information. | |
| using | error_terms_t = std::unordered_map<error_term_t, value_t> |
| Type used to map error terms to their radii. | |
| using | interval_t = Interval<value_t> |
| Type of an interval. | |
Public Member Functions | |
| Affine ()=default | |
| Constructs an empty affine form. | |
| Affine (value_t center) | |
| Constructs an affine form from a center value. | |
| Affine (value_t lo, value_t hi) | |
| Constructs an affine form from a lower and upper bound. | |
| Affine (const interval_t &interval) | |
| Constructs an affine form from an interval. | |
| Affine (value_t center, error_terms_t radii) | |
| Construct an affine form from a center value and a map of errors. | |
| Affine (const Affine &other)=default | |
Makes a deep copy of other. | |
| Affine (Affine &&other) noexcept=default | |
Constructs an affine form by moving other. | |
| Affine & | operator= (const Affine &other)=default |
Assigns the value of other to this affine form. | |
| Affine & | operator= (Affine &&other) noexcept=default |
Moves the value of other to this affine form. | |
| interval_t | range () const |
| Returns the interval represented by the affine form. | |
| value_t | center () const |
| Returns the center of the affine form. | |
| const error_terms_t & | error_terms () const |
| Returns the error terms of the affine form. | |
| value_t | radius () const |
| Returns the radius of the affine form. | |
| void | set_center (value_t center) |
| Sets the center of the affine form. | |
| void | add_error_term (error_term_t error_term, value_t radius) |
| Adds an error term to the affine form. | |
| bool | contains (value_t value) const |
Checks if the interval represented by *this contains value. | |
| bool | contains (const interval_t &interval) const |
Checks if interval is contained within *this. | |
| bool | contains (const Affine &affine) const |
Checks if affine is contained within *this. | |
| bool | empty () const noexcept |
| Checks if this affine form is representing an empty interval. | |
| std::string | print_affine_form () const |
| Creates a string of the affine form of *this. | |
| std::string | print_interval_form () const |
| Creates a string of the interval form of *this. | |
| Affine | operator- () const |
| Returns the additive inverse of *this. | |
| Affine & | operator+= (value_t value) |
Overwrites *this with the sum of *this and value. | |
| Affine & | operator+= (const Affine &other) |
Overwrites *this with the sum of *this and other. | |
| Affine | operator+ (value_t value) const |
Returns the sum of *this and value. | |
| Affine | operator+ (const Affine &other) const |
Returns the sum of *this and other. | |
| Affine & | operator-= (value_t value) |
Overwrites *this with the difference of *this and value. | |
| Affine & | operator-= (const Affine &other) |
Overwrites *this with the difference of *this and other. | |
| Affine | operator- (value_t value) const |
Returns the difference of *this and value. | |
| Affine | operator- (const Affine &other) const |
Returns the difference of *this and other. | |
| Affine & | operator*= (value_t value) |
Overwrites *this with the product of *this and value. | |
| Affine & | operator*= (const Affine &other) |
Overwrites *this with the product of *this and other. | |
| Affine | operator* (value_t value) const |
Returns the product of *this and value. | |
| Affine | operator* (const Affine &other) const |
Returns the product of *this and other. | |
| Affine & | operator/= (value_t value) |
Overwrites *this with the quotient of *this and value. | |
| Affine & | operator/= (const Affine &other) |
Overwrites *this with the quotient of *this and other. | |
| Affine | operator/ (value_t value) const |
Returns the quotient of *this and value. | |
| Affine | operator/ (const Affine &other) const |
Returns the quotient of *this and other. | |
| Affine | apply_affine_transform (value_t alpha, value_t zeta, value_t delta) const |
| Applies an affine transformation to *this. | |
| Affine | multiplicative_inverse () const |
| Returns the multiplicative inverse of *this. | |
| bool | operator== (const Affine &other) const |
Checks if *this and other represent the same affine form. | |
| bool | operator!= (const Affine &other) const |
Checks if *this and other represent different affine forms. | |
Related Symbols | |
(Note that these are not member symbols.) | |
| template<typename ValueType> | |
| std::ostream & | operator<< (std::ostream &os, const Affine< ValueType > &a) |
| Outputs the range of an affine form to an output stream. | |
| template<typename ValueType> | |
| Affine< ValueType > | operator* (ValueType value, const Affine< ValueType > &a) |
| Multiplies a scalar by an affine form. | |
Implements affine arithmetic.
| ValueType | The numeric type of the center and error term radii. |
Follows https://www.tuhh.de/ti3/paper/rump/RuKas14.pdf.
Affine arithmetic is a way to represent a range of values (an interval) as a center value and a set of error terms. Each error term has a symbol (an opaque object that uniquely identifies the error term) and a radius (a value that represents the maximum error from the center value for that error term).
Mathematically, an affine form can be represented as:
\[ x = x_0 + \sum_{i=1}^n x_i \epsilon_i \]
where \(x_0\) is the center, \(x_i\) are the error term radii, and \(\epsilon_i\) are the error term symbols. The error term symbols are assumed to be independent and can take on any value in the range [-1, 1]. Therefore, the affine form represents all values that can be obtained by substituting any value in [-1, 1] for each error term symbol.
Unlike traditional intervals, affine arithmetic can capture dependencies between variables. For example, if we have an affine value x that represents the range [1, 2], we can represent it as x = 1.5 + 0.5*e1, where e1 is an error term with radius 0.5. If we then define y = x - x, we can represent y as y = (1.5 + 0.5*e1) - (1.5 + 0.5*e1) = 0, which captures the fact that y is always 0 regardless of the value of e1. In contrast, if we were to represent x and y as traditional intervals, we would have x = [1, 2] and y = [-1, 1], because intervals do not track the dependency between x and y.
N.b. The current implementation of the Affine class does not track uncertainty from floating point arithmetic.
|
default |
Constructs an empty affine form.
An empty affine form represents the empty set.
| none | No throw guarantee |
|
inline |
Constructs an affine form from a center value.
The resulting affine form has no error terms and represents the single value given by the center.
| [in] | center | The center value of the affine form. |
| none | No throw guarantee |
|
inline |
Constructs an affine form from a lower and upper bound.
The resulting affine form has a single error term and represents the interval defined by the lower and upper bounds.
| [in] | lo | The lower bound of the interval represented by the affine form. |
| [in] | hi | The upper bound of the interval represented by the affine form. |
| std::bad_alloc | If memory allocation for the error term fails. Strong throw guarantee. |
|
inlineexplicit |
Constructs an affine form from an interval.
For a non-empty interval, the resulting affine form has a single error term and represents the interval defined by the lower and upper bounds of interval. If interval is empty, the resulting affine form is also empty.
| [in] | interval | The interval represented by the affine form. |
| std::bad_alloc | If memory allocation for the error term fails. Strong throw guarantee. |
|
inline |
Construct an affine form from a center value and a map of errors.
This constructor allows for the creation of an affine form by specifying the full state of the affine form (the center and the error terms). This ctor is meant primarily for use by other parts of Sigma, but can be used by users as well.
| [in] | center | The center value of the affine form. |
| [in] | radii | A map of error terms to their radii. |
| none | No throw guarantee |
|
default |
Makes a deep copy of other.
| [in] | other | The affine form to copy. |
| std::bad_alloc | If memory allocation for the error terms fails. Strong throw guarantee. |
|
defaultnoexcept |
Constructs an affine form by moving other.
| [in] | other | The affine form to move. |
| none | No throw guarantee |
|
inline |
Adds an error term to the affine form.
This method allows a new error term to be added to the affine form. The radius of the affine form is increased by the radius of the new error term. If the affine form is empty, the center is set to 0 before adding the error term (consistent with the idea that the resulting affine form should represent the interval [-radius, radius]).
| [in] | error_term | The symbol representing the new error term. |
| [in] | radius | The radius of the new error term. |
| None | No throw guarantee. |
|
inline |
Applies an affine transformation to *this.
Affine transformations are linear transformations characterized by two parameters: a scale factor and a shift. Often we will want to apply a non-affine transformation. To do this, we find an affine transformation that approximates the non-affine transformation (i.e., a scale factor and a shift for the approximate transformation) and an estimate of the error from using the approximate transformation.
N.b. applying an affine transformation to an empty affine form will result in the affine form \(\zeta \pm \delta\).
| [in] | alpha | The scale factor. |
| [in] | zeta | The shift. |
| [in] | delta | The error term. |
| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
|
inline |
Returns the center of the affine form.
| std::domain_error | If the affine form is empty (i.e., it has no center and no error terms). Strong throw guarantee. |
|
inline |
Checks if affine is contained within *this.
This method will ensure that each point in affine is contained in *this. In practice, this method is a convenience method for calling contains(affine.range()).
| [in] | affine | The affine form to check. |
| none | No throw guarantee |
| auto sigma::Affine< ValueType >::contains | ( | const interval_t & | interval | ) | const |
Checks if interval is contained within *this.
This method will ensure that each point in interval is contained in *this. Conceptually, this is equivalent to looping over values in interval and calling contains(value) for each value. In practice, this method only checks the endpoints of interval.
| [in] | interval | The interval to check. |
| none | No throw guarantee |
| auto sigma::Affine< ValueType >::contains | ( | value_t | value | ) | const |
Checks if the interval represented by *this contains value.
This method checks if a single value is contained within this->range(). By definition, if *this is empty, this method will return false for all values.
| [in] | value | The value to check. |
| none | No throw guarantee |
|
inlinenoexcept |
Checks if this affine form is representing an empty interval.
An affine form representing an empty interval has no center and no error terms. Viewed as an interval, it represents the empty set.
| none | No throw guarantee |
|
inline |
Returns the error terms of the affine form.
The error terms are returned a map where the keys are symbolic representations of the error terms and and the values are the radii of the error terms. The symbols are opaque objects that uniquely identify each error source. The symbols themselves have no meaning outside of the context of the affine form except that they satisfy the property that if two error symbols are equal, then they represent the same error source.
| None | No throw guarantee. |
| auto sigma::Affine< ValueType >::multiplicative_inverse | ( | ) | const |
Returns the multiplicative inverse of *this.
The multiplicative inverse of an affine form \(x\) is obtained by applying an affine transformation to *this. The parameters of this transformation are given by:
\[\begin{align} a &= \min(|lo|, |hi|) \\ b &= \max(|lo|, |hi|) \\ \alpha &= -\frac{1}{b^2} \\ i &= \left[\frac{1}{a} - \alpha a, \frac{2}{b}\right]\\ \zeta &= |midpoint(i)|\\ \delta &= radius(i) \end{align} \]
Where \(lo\) and \(hi\) are the lower and upper bounds of *this.
| std::domain_error | If *this is empty or contains zero. Strong throw guarantee. |
|
inline |
Checks if *this and other represent different affine forms.
Two affine forms are considered different if they are not equal according to the definition of equality given in operator==. See the documentation for operator== for details on how affine forms are compared.
| [in] | other | The affine form to compare with *this. |
other represent different affine forms, false otherwise.| none | No throw guarantee. |
|
inline |
Returns the product of *this and other.
This is a convenience method for calling Affine(*this) *= other. See the documentation for operator*=(Affine) for details on how multiplication with another affine form works.
| [in] | other | The affine form to multiply *this by. |
other.| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
|
inline |
Returns the product of *this and value.
This is a convenience method for calling Affine(*this) *= value. See the documentation for operator*=(value_t) for details on how multiplication with a scalar works.
| [in] | value | The value to multiply *this by. |
value.| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
| auto sigma::Affine< ValueType >::operator*= | ( | const Affine< ValueType > & | other | ) |
Overwrites *this with the product of *this and other.
The product of two affine forms \(x\) and \(y\) is defined as:
\[x y = x_0 y_0 + \sum_{i=1}^n (x_0 y_i + x_i y_0) \epsilon_i + xy_{n+1} \epsilon_{n+1} \]
where \(xy_{n+1}\) is an error term that captures the error from the nonlinearity of multiplication. The current implementation of the Affine class uses:
\[xy_{n+1} = \sum_{i=1}^n \sum_{j=1}^n |x_i y_j| \]
which is the product of the radii of the error terms of \(x\) and \(y\).
| [in] | other | The affine form to multiply *this by. |
| None | No throw guarantee. |
|
inline |
Overwrites *this with the product of *this and value.
The product of an affine form \(x\) and a scalar \(\alpha\) is defined as:
\[\alpha x = \alpha x_0 + \sum_{i=1}^n \alpha x_i \epsilon_i \]
| [in] | value | The value to multiply *this by. |
| None | No throw guarantee. |
|
inline |
Returns the sum of *this and other.
This is a convenience method for calling Affine(*this) += other. See the documentation for operator+=(Affine) for details on how addition with another affine form works.
| [in] | other | The affine form to add to *this. |
other.| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
|
inline |
Returns the sum of *this and value.
This is a convenience method for calling Affine(*this) += value. See the documentation for operator+=(value_t) for details on how addition with a scalar works.
| [in] | value | The value to add to *this. |
value.| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
| auto sigma::Affine< ValueType >::operator+= | ( | const Affine< ValueType > & | other | ) |
Overwrites *this with the sum of *this and other.
Addition of affine forms \(x\) and \(y\) is defined as:
\[x + y = (x_0 + y_0) + \sum_{i=1}^n (x_i + y_i) \epsilon_i \]
Critically, the error terms are only summed if they have the same symbol. If an error term appears in one affine form but not the other, the resulting affine form will have an error term with the same symbol and the same radius as the original affine form.
| [in] | other | The affine form to add to *this. |
| None | No throw guarantee. |
|
inline |
Overwrites *this with the sum of *this and value.
If *this is empty, the resulting affine form will have a center of value and no error terms. Otherwise this method will add value to the center of *this and leave the error terms unchanged.
| [in] | value | The value to add to *this. |
| None | No throw guarantee. |
| auto sigma::Affine< ValueType >::operator- | ( | ) | const |
Returns the additive inverse of *this.
The additive inverse of an affine form is the affine form:
\[ -x = -x_0 + \sum_{i=1}^n -x_i \epsilon_i \]
| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
|
inline |
Returns the difference of *this and other.
This is a convenience method for calling Affine(*this) -= other. See the documentation for operator-=(Affine) for details on how subtraction with another affine form works.
| [in] | other | The affine form to subtract from *this. |
other.| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
|
inline |
Returns the difference of *this and value.
This is a convenience method for calling Affine(*this) -= value. See the documentation for operator-=(value_t) for details on how subtraction with a scalar works.
| [in] | value | The value to subtract from *this. |
value.| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
| auto sigma::Affine< ValueType >::operator-= | ( | const Affine< ValueType > & | other | ) |
Overwrites *this with the difference of *this and other.
Subtraction of affine forms \(x\) and \(y\) is defined as:
\[x - y = (x_0 - y_0) + \sum_{i=1}^n (x_i - y_i) \epsilon_i \]
Critically, the error terms are only subtracted if they have the same symbol. If an error term appears in one affine form but not the other, the resulting affine form will have an error term with the same symbol and the same radius as the original affine form.
| [in] | other | The affine form to subtract from *this. |
| None | No throw guarantee. |
|
inline |
Overwrites *this with the difference of *this and value.
If *this is empty, the resulting affine form will have a center of value and no error terms. Otherwise this method will subtract value from the center of *this and leave the error terms unchanged.
| [in] | value | The value to subtract from *this. |
| None | No throw guarantee. |
|
inline |
Returns the quotient of *this and other.
This is a convenience method for calling Affine(*this) /= other. See the documentation for operator/=(Affine) for details on how division with another affine form works.
| [in] | other | The affine form to divide *this by. |
other.| std::domain_error | If other is empty or has a zero center. Strong throw guarantee. |
| std::bad_alloc | If memory allocation for the multiplicative inverse of other fails. Strong throw guarantee. |
|
inline |
Returns the quotient of *this and value.
This is a convenience method for calling Affine(*this) /= value. See the documentation for operator/=(value_t) for details on how division with a scalar works.
| [in] | value | The value to divide *this by. |
value.| std::domain_error | If value is zero. |
| auto sigma::Affine< ValueType >::operator/= | ( | const Affine< ValueType > & | other | ) |
Overwrites *this with the quotient of *this and other.
This method is implemented as the product of this and other.multiplicative_inverse(). See the documentation for `operator=(Affine)` and multiplicative_inverse() for more details on how these operations work.
| [in] | other | The affine form to divide *this by. |
| std::domain_error | If other is empty or has a zero center. Strong throw guarantee. |
| std::bad_alloc | If memory allocation for the multiplicative inverse of other fails. Strong throw guarantee. |
|
inline |
Overwrites *this with the quotient of *this and value.
The quotient of an affine form \(x\) and a scalar \(\alpha\) is defined as:
\[ \frac{x}{\alpha} = \frac{x_0}{\alpha} + \sum_{i=1}^n \frac{x_i}{\alpha} \epsilon_i \]
| [in] | value | The value to divide *this by. |
| std::domain_error | If value is zero. |
|
defaultnoexcept |
Moves the value of other to this affine form.
| [in] | other | The affine form to move. |
| none | No throw guarantee. |
|
default |
Assigns the value of other to this affine form.
| [in] | other | The affine form to assign. |
| std::bad_alloc | If memory allocation for the error terms fails. Strong throw guarantee. |
|
inline |
Checks if *this and other represent the same affine form.
Two affine forms are considered equal if they are both empty or if they have the same center and the same error terms. Note that the order in which the error terms are stored in the error_terms_t map is not guaranteed to be the same, but this method does not check the order of the error terms, only that each symbol is present.
| [in] | other | The affine form to compare with *this. |
other represent the same affine form, false otherwise.| none | No throw guarantee. |
| std::string sigma::Affine< ValueType >::print_affine_form | ( | ) | const |
Creates a string of the affine form of *this.
The affine form is written as the center value +/- each of the error terms. If *this contains multiple error terms, the order in which the error terms are printed is NOT guaranteed to be the same across multiple runs of the program.
| std::bad_alloc | If memory allocation for the string fails. Strong throw guarantee. |
|
inline |
Creates a string of the interval form of *this.
The interval form of *this is the same as the affine form, except that the error terms are combined into a single radius term. Following, usual convention, the interval form is written in the form [center - radius, center + radius].
This is a convenience method for calling range().print_interval_form().
| std::bad_alloc | If memory allocation for the string fails. Strong throw guarantee. |
| auto sigma::Affine< ValueType >::radius | ( | ) | const |
Returns the radius of the affine form.
The radius is the sum of the absolute values of the error terms.
| std::domain_error | If the affine form is empty (i.e., it has no center and no error terms). Strong throw guarantee. |
| auto sigma::Affine< ValueType >::range | ( | ) | const |
Returns the interval represented by the affine form.
Note that the interval returned by this method is always closed on both ends.
| none | No throw guarantee |
|
inline |
Sets the center of the affine form.
This method allows the center of the affine form to be updated. The error terms are not modified by this method, so the radius of the affine form is not changed by this method.
| [in] | center | The new center of the affine form. |
| None | No throw guarantee. |
|
Multiplies a scalar by an affine form.
| ValueType | The type of the values in the affine form. |
This method implements multiplication of a scalar by an affine form. It is a convenience method for calling Affine(*this) *= value. See the documentation for operator*=(value_t) for details on how multiplication with a scalar works.
| [in] | value | The scalar to multiply by. |
| [in] | a | The affine form to multiply. |
| std::bad_alloc | If memory allocation for the new affine form fails. Strong throw guarantee. |
|
Outputs the range of an affine form to an output stream.
| ValueType | The type of the values in the affine form. |
This method will defer to the output operator for interval_t to print the value of the affine form. See the documentation for interval_t for details on how intervals are printed.
| [in] | os | The output stream to write to. |
| [in] | a | The affine form to output. |
| none | No throw guarantee. |