6#include <unordered_map>
47template<
typename ValueType>
114 if(interval.
empty()) {
return; }
115 m_center_ = interval.
median();
116 if(interval.
radius() > 0) {
134 m_center_(
center), m_error_terms_(std::move(radii)) {}
253 m_error_terms_[error_term] =
radius;
313 bool empty() const noexcept {
return !m_center_; }
377 (*m_center_) += value;
429 return Affine(*
this) += other;
446 (*m_center_) -= value;
498 return Affine(*
this) -= other;
516 if(
empty()) {
return *
this; }
517 (*m_center_) *= value;
518 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
519 error_term_i *= value;
577 return Affine(*
this) *= other;
596 if(value == 0) {
throw std::domain_error(
"Division by zero"); }
597 return *
this *=
value_t(1.0 / value);
648 return Affine(*
this) /= other;
677 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
678 new_error_terms[error_symbol] = alpha * error_term_i;
681 return Affine(new_center, std::move(new_error_terms));
727 if(
empty() != other.
empty()) {
return false; }
728 if(
empty()) {
return true; }
729 if(m_center_ != other.m_center_) {
return false; }
730 return m_error_terms_ == other.m_error_terms_;
752 static std::atomic<size_type> s_next_id{0};
753 return s_next_id.fetch_add(1);
758 void assert_not_empty_()
const {
759 if(
empty()) {
throw std::domain_error(
"Affine form is empty"); }
764 std::optional<value_t> m_center_;
790template<
typename ValueType>
814template<
typename ValueType>
822template<
typename ValueType>
829template<
typename ValueType>
833 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
834 r += std::fabs(error_term_i);
839template<
typename ValueType>
841 if(
empty()) {
return false; }
842 return range().contains(value);
845template<
typename ValueType>
847 if(interval.empty()) {
return true; }
848 if(
empty()) {
return false; }
849 return range().contains(interval);
852template<
typename ValueType>
854 if(
empty()) {
return "∅"; }
855 std::stringstream ss;
857 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
858 ss <<
" +/- " << error_term_i;
863template<
typename ValueType>
865 if(
empty()) {
return *
this; }
868 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
869 new_error_terms[error_symbol] = -error_term_i;
871 return Affine(new_center, new_error_terms);
874template<
typename ValueType>
876 if(
empty()) {
return *
this = other; }
877 if(other.empty()) {
return *
this; }
880 for(
auto&& [error_symbol, error_term_i] : other.m_error_terms_) {
881 new_error_terms[error_symbol] += error_term_i;
883 return *
this =
Affine(new_center, new_error_terms);
886template<
typename ValueType>
888 return *
this += -other;
891template<
typename ValueType>
893 if(
empty() || other.empty()) {
return *
this =
Affine(); }
897 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
898 new_error_terms[error_symbol] = error_term_i * other.center();
899 new_radius += std::fabs(new_error_terms[error_symbol]);
901 for(
auto&& [error_symbol, error_term_j] : other.m_error_terms_) {
902 new_error_terms[error_symbol] += error_term_j *
center();
903 new_radius += std::fabs(new_error_terms[error_symbol]);
905 auto correction =
radius() * other.radius();
907 return *
this =
Affine(new_center, new_error_terms);
910template<
typename ValueType>
913 return *
this *= other.multiplicative_inverse();
916template<
typename ValueType>
919 if(
contains(0)) {
throw std::domain_error(
"Division by zero"); }
921 auto other_range =
range();
922 auto abs_inf = std::fabs(other_range.lower());
923 auto abs_sup = std::fabs(other_range.upper());
924 auto a = std::min(abs_inf, abs_sup);
925 auto b = std::max(abs_inf, abs_sup);
926 auto alpha =
value_t(-1.0) / (b * b);
927 auto lo =
value_t(1.0) / a - alpha * a;
929 interval_t interval(std::min(lo, hi), std::max(lo, hi));
930 auto zeta = std::fabs(interval.
median());
931 auto delta = interval.
radius();
Components for compatibility with Eigen.
Convenience header for affine form operations.
Implements affine arithmetic.
Definition affine.hpp:48
Affine operator+(const Affine &other) const
Returns the sum of *this and other.
Definition affine.hpp:428
Affine & operator/=(value_t value)
Overwrites *this with the quotient of *this and value.
Definition affine.hpp:595
Affine & operator-=(value_t value)
Overwrites *this with the difference of *this and value.
Definition affine.hpp:444
bool contains(const Affine &affine) const
Checks if affine is contained within *this.
Definition affine.hpp:299
Affine< ValueType > operator*(ValueType value, const Affine< ValueType > &a)
Multiplies a scalar by an affine form.
Definition affine.hpp:815
Affine & operator-=(const Affine &other)
Overwrites *this with the difference of *this and other.
Definition affine.hpp:887
Affine & operator+=(value_t value)
Overwrites *this with the sum of *this and value.
Definition affine.hpp:375
Affine(value_t center, error_terms_t radii)
Construct an affine form from a center value and a map of errors.
Definition affine.hpp:133
bool operator==(const Affine &other) const
Checks if *this and other represent the same affine form.
Definition affine.hpp:726
Affine operator+(value_t value) const
Returns the sum of *this and value.
Definition affine.hpp:413
Affine apply_affine_transform(value_t alpha, value_t zeta, value_t delta) const
Applies an affine transformation to *this.
Definition affine.hpp:673
Affine operator/(value_t value) const
Returns the quotient of *this and value.
Definition affine.hpp:630
bool contains(const interval_t &interval) const
Checks if interval is contained within *this.
Definition affine.hpp:846
Affine()=default
Constructs an empty affine form.
ValueType value_t
Type used for storing floating point values.
Definition affine.hpp:54
Affine(Affine &&other) noexcept=default
Constructs an affine form by moving other.
std::unordered_map< error_term_t, value_t > error_terms_t
Type used to map error terms to their radii.
Definition affine.hpp:60
std::string print_interval_form() const
Creates a string of the interval form of *this.
Definition affine.hpp:343
Affine(value_t lo, value_t hi)
Constructs an affine form from a lower and upper bound.
Definition affine.hpp:99
const error_terms_t & error_terms() const
Returns the error terms of the affine form.
Definition affine.hpp:213
Affine multiplicative_inverse() const
Returns the multiplicative inverse of *this.
Definition affine.hpp:917
Affine(value_t center)
Constructs an affine form from a center value.
Definition affine.hpp:84
std::string print_affine_form() const
Creates a string of the affine form of *this.
Definition affine.hpp:853
value_t center() const
Definition affine.hpp:194
Affine(const Affine &other)=default
Makes a deep copy of other.
Affine operator-(value_t value) const
Returns the difference of *this and value.
Definition affine.hpp:482
size_type error_term_t
Opaque type used to store error term information.
Definition affine.hpp:57
void set_center(value_t center)
Sets the center of the affine form.
Definition affine.hpp:236
Interval< value_t > interval_t
Type of an interval.
Definition affine.hpp:63
Affine operator*(const Affine &other) const
Returns the product of *this and other.
Definition affine.hpp:576
Affine & operator*=(value_t value)
Overwrites *this with the product of *this and value.
Definition affine.hpp:515
static error_term_t make_error_term()
Returns a process-wide unique integer ID for a new error term symbol.
Definition affine.hpp:751
bool operator!=(const Affine &other) const
Checks if *this and other represent different affine forms.
Definition affine.hpp:748
Affine & operator*=(const Affine &other)
Overwrites *this with the product of *this and other.
Definition affine.hpp:892
Affine & operator=(Affine &&other) noexcept=default
Moves the value of other to this affine form.
std::size_t size_type
Type used for indexing and offsets.
Definition affine.hpp:51
Affine operator-(const Affine &other) const
Returns the difference of *this and other.
Definition affine.hpp:497
void add_error_term(error_term_t error_term, value_t radius)
Adds an error term to the affine form.
Definition affine.hpp:251
Affine operator*(value_t value) const
Returns the product of *this and value.
Definition affine.hpp:561
bool empty() const noexcept
Checks if this affine form is representing an empty interval.
Definition affine.hpp:313
std::ostream & operator<<(std::ostream &os, const Affine< ValueType > &a)
Outputs the range of an affine form to an output stream.
Definition affine.hpp:791
Affine & operator/=(const Affine &other)
Overwrites *this with the quotient of *this and other.
Definition affine.hpp:911
interval_t range() const
Returns the interval represented by the affine form.
Definition affine.hpp:823
bool contains(value_t value) const
Checks if the interval represented by *this contains value.
Definition affine.hpp:840
Affine operator/(const Affine &other) const
Returns the quotient of *this and other.
Definition affine.hpp:647
Affine & operator+=(const Affine &other)
Overwrites *this with the sum of *this and other.
Definition affine.hpp:875
Affine(const interval_t &interval)
Constructs an affine form from an interval.
Definition affine.hpp:113
Affine operator-() const
Returns the additive inverse of *this.
Definition affine.hpp:864
Affine & operator=(const Affine &other)=default
Assigns the value of other to this affine form.
value_t radius() const
Returns the radius of the affine form.
Definition affine.hpp:830
Models a numeric interval.
Definition interval.hpp:23
value_t median() const
Returns the midpoint of the interval.
Definition interval.hpp:82
std::string print_interval_form() const
Print the interval in interval form.
Definition interval.hpp:604
value_t radius() const
Returns the half-width of the interval.
Definition interval.hpp:96
bool empty() const
Is *this the empty interval?
Definition interval.hpp:106
Defines the Interval class.
The primary namespace for the sigma library.
Definition affine.hpp:12
Affine< double > ADouble
Typedef for an affine form of doubles.
Definition affine.hpp:939
Affine< float > AFloat
Typedef for an affine form of floats.
Definition affine.hpp:936