9 if(a.
empty()) {
return a; }
10 auto a_range = a.
range();
11 auto lo = a_range.
lower();
12 auto hi = a_range.upper();
13 if(lo < 0) {
throw std::domain_error(
"Affine form has negative values."); }
15 auto sqrt_lower = std::sqrt(lo);
16 auto sqrt_upper = std::sqrt(hi);
18 auto sqrt_sum = sqrt_upper + sqrt_lower;
19 auto sqrt_diff = sqrt_upper - sqrt_lower;
20 auto sqrt_prod = sqrt_upper * sqrt_lower;
22 auto alpha = T(1.0) / (sqrt_sum);
23 auto zeta = sqrt_sum / T(8.0) + T(0.5) * sqrt_prod / sqrt_sum;
24 auto delta = sqrt_diff * sqrt_diff / (T(8.0) * sqrt_sum);
31 auto a_range = a.
range();
32 auto hi = a_range.
upper();
33 auto lo = a_range.lower();
34 if(hi - lo == 0) {
return Affine<T>(std::exp(lo)); }
38 auto exp_lower = std::exp(lo);
39 auto exp_upper = std::exp(hi);
40 auto alpha = (exp_upper - exp_lower) / (hi - lo);
41 auto log_alpha = std::log(alpha);
42 auto c_chord = exp_lower - alpha * lo;
43 auto c_tangent = alpha * (one - log_alpha);
44 auto zeta = (c_chord + c_tangent) / two;
45 auto delta = (c_chord - c_tangent) / two;
51 auto a_range = a.
range();
52 auto hi = a_range.
upper();
53 auto lo = a_range.lower();
55 throw std::domain_error(
"Affine form has non-positive values.");
57 if(hi - lo == 0) {
return Affine<T>(std::log(lo)); }
59 auto log_lo = std::log(lo);
60 auto alpha = (std::log(hi) - log_lo) / (hi - lo);
61 auto xs = T(1.0) / alpha;
62 auto ys = alpha * (xs - lo) + log_lo;
63 auto log_xs = std::log(xs);
64 auto zeta = (log_xs + ys) / 2 - alpha * xs;
65 auto delta = (log_xs - ys) / 2;
70template<
typename T,
typename U>
73 if(a.
empty()) {
return a; }
78 throw std::domain_error(
79 "Can not raise an affine form containing 0 to a negative power.");
86 using clean_u_t = std::decay_t<U>;
87 if constexpr(std::is_floating_point_v<clean_u_t>) {
89 if(std::modf(
exp, &exp_int) != zero) {
90 throw std::domain_error(
91 "Can not raise an affine form with negative values to a "
92 "non-integer power.");
98 const bool exp_is_even =
static_cast<long long>(
exp) % 2 == 0;
99 return exp_is_even ? pow_abs : -pow_abs;
Defines the Affine class.
Implements affine arithmetic.
Definition affine.hpp:48
Affine apply_affine_transform(value_t alpha, value_t zeta, value_t delta) const
Applies an affine transformation to *this.
Definition affine.hpp:673
bool empty() const noexcept
Checks if this affine form is representing an empty interval.
Definition affine.hpp:313
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
value_t upper() const
Returns the upper bound of the interval.
Definition interval.hpp:157
value_t lower() const
Returns the lower bound of the interval.
Definition interval.hpp:146
The primary namespace for the sigma library.
Definition affine.hpp:12
Affine< T > exp(const Affine< T > &a)
Calculate the exponential of an affine form.
Definition exponents.ipp:30
Affine< T > pow(const Affine< T > &a, const U &exp)
Calculate the power of an affine form.
Definition exponents.ipp:71
Affine< T > log(const Affine< T > &a)
Calculate the natural logarithm of an affine form.
Definition exponents.ipp:50
Affine< T > sqrt(const Affine< T > &a)
Calculate the square root of an affine form.
Definition exponents.ipp:8