6#include <unordered_map>
47template<
typename ValueType>
114 if(interval.
empty()) {
return; }
115 m_center_ = interval.
median();
116 if(interval.
radius() > 0) {
117 m_error_terms_[make_error_term()] = interval.
radius();
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;
680 new_error_terms[make_error_term()] = delta;
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 void assert_not_empty_()
const {
753 if(
empty()) {
throw std::domain_error(
"Affine form is empty"); }
760 return std::make_shared<size_type>(m_error_terms_.size());
765 std::optional<value_t> m_center_;
791template<
typename ValueType>
815template<
typename ValueType>
823template<
typename ValueType>
830template<
typename ValueType>
834 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
835 r += std::fabs(error_term_i);
840template<
typename ValueType>
842 if(
empty()) {
return false; }
843 return range().contains(value);
846template<
typename ValueType>
848 if(interval.empty()) {
return true; }
849 if(
empty()) {
return false; }
850 return range().contains(interval);
853template<
typename ValueType>
855 if(
empty()) {
return "∅"; }
856 std::stringstream ss;
858 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
859 ss <<
" +/- " << error_term_i;
864template<
typename ValueType>
866 if(
empty()) {
return *
this; }
869 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
870 new_error_terms[error_symbol] = -error_term_i;
872 return Affine(new_center, new_error_terms);
875template<
typename ValueType>
877 if(
empty()) {
return *
this = other; }
878 if(other.empty()) {
return *
this; }
881 for(
auto&& [error_symbol, error_term_i] : other.m_error_terms_) {
882 new_error_terms[error_symbol] += error_term_i;
884 return *
this =
Affine(new_center, new_error_terms);
887template<
typename ValueType>
889 return *
this += -other;
892template<
typename ValueType>
894 if(
empty() || other.empty()) {
return *
this =
Affine(); }
898 for(
auto&& [error_symbol, error_term_i] : m_error_terms_) {
899 new_error_terms[error_symbol] = error_term_i * other.center();
900 new_radius += std::fabs(new_error_terms[error_symbol]);
902 for(
auto&& [error_symbol, error_term_j] : other.m_error_terms_) {
903 new_error_terms[error_symbol] += error_term_j *
center();
904 new_radius += std::fabs(new_error_terms[error_symbol]);
906 auto correction =
radius() * other.radius();
907 new_error_terms[make_error_term()] = correction;
908 return *
this =
Affine(new_center, new_error_terms);
911template<
typename ValueType>
914 return *
this *= other.multiplicative_inverse();
917template<
typename ValueType>
920 if(
contains(0)) {
throw std::domain_error(
"Division by zero"); }
922 auto other_range =
range();
923 auto abs_inf = std::fabs(other_range.lower());
924 auto abs_sup = std::fabs(other_range.upper());
925 auto a = std::min(abs_inf, abs_sup);
926 auto b = std::max(abs_inf, abs_sup);
927 auto alpha =
value_t(-1.0) / (b * b);
928 auto lo =
value_t(1.0) / a - alpha * a;
930 interval_t interval(std::min(lo, hi), std::max(lo, hi));
931 auto zeta = std::fabs(interval.
median());
932 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:816
Affine & operator-=(const Affine &other)
Overwrites *this with the difference of *this and other.
Definition affine.hpp:888
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:847
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:918
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:854
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
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
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:893
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:792
std::shared_ptr< size_type > error_term_t
Opaque type used to store error term information.
Definition affine.hpp:57
Affine & operator/=(const Affine &other)
Overwrites *this with the quotient of *this and other.
Definition affine.hpp:912
interval_t range() const
Returns the interval represented by the affine form.
Definition affine.hpp:824
bool contains(value_t value) const
Checks if the interval represented by *this contains value.
Definition affine.hpp:841
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:876
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:865
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:831
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:940
Affine< float > AFloat
Typedef for an affine form of floats.
Definition affine.hpp:937