SIROCCO2/lib/mp_interval.cpp
2020-02-11 11:38:13 +00:00

564 lines
15 KiB
C++

#include "mp_interval.hpp"
// MACROS FOR MIN AND MAX
#define MIN(a,b) (((a) < (b))? (a) : (b))
#define MAX(a,b) (((a) > (b))? (a) : (b))
// DEFAULT CONSTRUCTOR
MPInterval::MPInterval (double op) {
mpfr_init_set_d (a, op, MPFR_RNDD);
mpfr_init_set_d (b, op, MPFR_RNDU);
}
// CONSTRUCTOR BY double ELEMENTS
MPInterval::MPInterval (double op1, double op2) {
mpfr_init_set_d (a, op1, MPFR_RNDD);
mpfr_init_set_d (b, op2, MPFR_RNDU);
}
// CONSTRUCTOR BY string VALUE
MPInterval::MPInterval (const char *op) {
mpfr_init_set_str (a, op, 10, MPFR_RNDD);
mpfr_init_set_str (b, op, 10, MPFR_RNDU);
}
// CONSTRUCTOR BY string PAIR OF VALUES
MPInterval::MPInterval (const char *op1, const char *op2) {
mpfr_init_set_str (a, op1, 10, MPFR_RNDD);
mpfr_init_set_str (b, op2, 10, MPFR_RNDU);
}
// CONSTRUCTOR BY mpfr ELEMENT
MPInterval::MPInterval (const mpfr_t op) {
mpfr_init_set (a, op, MPFR_RNDD);
mpfr_init_set (b, op, MPFR_RNDU);
}
// CONSTRUCTOR BY mpfr PAIR OF ELEMENTS
MPInterval::MPInterval (const mpfr_t op1, const mpfr_t op2) {
mpfr_init_set (a, op1, MPFR_RNDD);
mpfr_init_set (b, op2, MPFR_RNDU);
}
// CONSTRUCTOR BY double Invterval
MPInterval::MPInterval (const Interval &op) {
mpfr_init_set_d (a, op.a, MPFR_RNDD);
mpfr_init_set_d (b, op.b, MPFR_RNDU);
}
// COPY CONSTRUCTOR
MPInterval::MPInterval (const MPInterval &op) {
mpfr_init_set (a, op.a, MPFR_RNDD);
mpfr_init_set (b, op.b, MPFR_RNDU);
}
// DESTRUCTOR
MPInterval::~MPInterval () {
mpfr_clears (a, b, NULL);
}
int MPInterval::operator== (double op) const {
return (mpfr_cmp_d(this->a, op) == 0) && (mpfr_cmp_d(this->b, op) == 0);
}
int MPInterval::operator== (const Interval &op) const {
return (mpfr_cmp_d (this->a, op.a) == 0) && (mpfr_cmp_d (this->b, op.b) == 0);
}
int MPInterval::operator== (const MPInterval &op) const {
return (mpfr_cmp(this->a, op.a) == 0) && (mpfr_cmp(this->b, op.b) == 0);
}
int MPInterval::operator!= (double op) const {
return (mpfr_cmp_d(this->a, op) != 0) || (mpfr_cmp_d(this->b, op) != 0);
}
int MPInterval::operator!= (const Interval &op) const {
return (mpfr_cmp_d (this->a, op.a) != 0) || (mpfr_cmp_d (this->b, op.b) != 0);
}
int MPInterval::operator!= (const MPInterval &op) const {
return (mpfr_cmp(this->a, op.a) != 0) || (mpfr_cmp(this->a, op.b) != 0);
}
// ASSIGNMENT
MPInterval & MPInterval::operator= (const MPInterval &op) {
// CHECK WHETER WE ARE ASIGNING SOMETHING OVER ITSELF
if (this == &op) return (*this);
// UPDATE VALUES
mpfr_set (this->a, op.a, MPFR_RNDD);
mpfr_set (this->b, op.b, MPFR_RNDU);
return *this;
}
MPInterval & MPInterval::operator= (const Interval &op) {
// UPDATE VALUES
mpfr_set_d (this->a, op.a, MPFR_RNDD);
mpfr_set_d (this->b, op.b, MPFR_RNDU);
return *this;
}
MPInterval & MPInterval::operator= (const mpfr_t op) {
// UPDATE VALUES
mpfr_set (this->a, op, MPFR_RNDD);
mpfr_set (this->b, op, MPFR_RNDU);
return *this;
}
MPInterval & MPInterval::operator= (double op) {
// UPDATE VALUES
mpfr_set_d (this->a, op, MPFR_RNDD);
mpfr_set_d (this->b, op, MPFR_RNDU);
return *this;
}
// ARITHMETIC
// [a,b] + [c,d] = [a+c, b+d]
MPInterval MPInterval::operator+ (const MPInterval &op) const {
MPInterval rop (*this);
mpfr_add (rop.a, rop.a, op.a, MPFR_RNDD);
mpfr_add (rop.b, rop.b, op.b, MPFR_RNDU);
return rop;
}
// [a,b] + [c,d] = [a+c, b+d]
MPInterval MPInterval::operator+ (const Interval &op) const {
MPInterval rop (*this);
mpfr_add_d (rop.a, rop.a, op.a, MPFR_RNDD);
mpfr_add_d (rop.b, rop.b, op.b, MPFR_RNDU);
return rop;
}
// [a,b] + c = [a+c, b+c]
MPInterval MPInterval::operator+ (const mpfr_t op) const {
MPInterval rop (*this);
mpfr_add (rop.a, rop.a, op, MPFR_RNDD);
mpfr_add (rop.b, rop.b, op, MPFR_RNDU);
return rop;
}
// [a,b] + c = [a+c, b+c]
MPInterval MPInterval::operator+ (double op) const {
MPInterval rop (*this);
mpfr_add_d (rop.a, rop.a, op, MPFR_RNDD);
mpfr_add_d (rop.b, rop.b, op, MPFR_RNDU);
return rop;
}
// CHANGE OF SIGN OF AN INTERVAL
// -[a,b] = [-b,a]
MPInterval MPInterval::operator- () const {
MPInterval rop;
mpfr_neg (rop.a, this->b, MPFR_RNDD);
mpfr_neg (rop.b, this->a, MPFR_RNDU);
return rop;
}
// [a,b] - [c,d] = [a-d, b-c]
MPInterval MPInterval::operator- (const MPInterval &op) const {
MPInterval rop(*this);
mpfr_sub (rop.a, rop.a, op.b, MPFR_RNDD);
mpfr_sub (rop.b, rop.b, op.a, MPFR_RNDU);
return rop;
}
// [a,b] - [c,d] = [a-d, b-c]
MPInterval MPInterval::operator- (const Interval &op) const {
MPInterval rop(*this);
mpfr_sub_d (rop.a, rop.a, op.b, MPFR_RNDD);
mpfr_sub_d (rop.b, rop.b, op.a, MPFR_RNDU);
return rop;
}
// [a,b] - c = [a-c, b-c]
MPInterval MPInterval::operator- (const mpfr_t op) const {
MPInterval rop(*this);
mpfr_sub (rop.a, rop.a, op, MPFR_RNDD);
mpfr_sub (rop.b, rop.b, op, MPFR_RNDU);
return rop;
}
// [a,b] - c = [a-c, b-c]
MPInterval MPInterval::operator- (double op) const {
MPInterval rop(*this);
mpfr_sub_d (rop.a, rop.a, op, MPFR_RNDD);
mpfr_sub_d (rop.b, rop.b, op, MPFR_RNDU);
return rop;
}
// [a,b]*[c,d] = [min(a*c,a*d,b*c,b*d), max(a*c,a*d,b*c,b*d)]
MPInterval MPInterval::operator* (const MPInterval &op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_mul (rop.a, this->a, op.a, MPFR_RNDD);
mpfr_mul (aux, this->a, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul (aux, this->b, op.a, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul (aux, this->b, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul (rop.b, this->a, op.a, MPFR_RNDU);
mpfr_mul (aux, this->a, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_mul (aux, this->b, op.a, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_mul (aux, this->b, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]*[c,d] = [min(a*c,a*d,b*c,b*d), max(a*c,a*d,b*c,b*d)]
MPInterval MPInterval::operator* (const Interval &op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_mul_d (rop.a, this->a, op.a, MPFR_RNDD);
mpfr_mul_d (aux, this->a, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul_d (aux, this->b, op.a, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul_d (aux, this->b, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul_d (rop.b, this->a, op.a, MPFR_RNDU);
mpfr_mul_d (aux, this->a, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_mul_d (aux, this->b, op.a, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_mul_d (aux, this->b, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]*c = [min(a*c,b*c), max(a*c,b*c)]
MPInterval MPInterval::operator* (const mpfr_t op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_mul (rop.a, this->a, op, MPFR_RNDD);
mpfr_mul (aux, this->b, op, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul (rop.b, this->a, op, MPFR_RNDU);
mpfr_mul (aux, this->b, op, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]*c = [min(a*c,b*c), max(a*c,b*c)]
MPInterval MPInterval::operator* (double op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_mul_d (rop.a, this->a, op, MPFR_RNDD);
mpfr_mul_d (aux, this->b, op, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_mul_d (rop.b, this->a, op, MPFR_RNDU);
mpfr_mul_d (aux, this->b, op, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]/[c,d] = [min(a/c,a/d,b/c,b/d), max(a/c,a/d,b/c,b/d)]
MPInterval MPInterval::operator/ (const MPInterval &op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_div (rop.a, this->a, op.a, MPFR_RNDD);
mpfr_div (aux, this->a, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div (aux, this->b, op.a, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div (aux, this->b, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div (rop.b, this->a, op.a, MPFR_RNDU);
mpfr_div (aux, this->a, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_div (aux, this->b, op.a, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_div (aux, this->b, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]/[c,d] = [min(a/c,a/d,b/c,b/d), max(a/c,a/d,b/c,b/d)]
MPInterval MPInterval::operator/ (const Interval &op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_div_d (rop.a, this->a, op.a, MPFR_RNDD);
mpfr_div_d (aux, this->a, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div_d (aux, this->b, op.a, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div_d (aux, this->b, op.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div_d (rop.b, this->a, op.a, MPFR_RNDU);
mpfr_div_d (aux, this->a, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_div_d (aux, this->b, op.a, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_div_d (aux, this->b, op.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]/c = [min(a/c,b/c), max(a/c,b/c)]
MPInterval MPInterval::operator/ (const mpfr_t op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_div (rop.a, this->a, op, MPFR_RNDD);
mpfr_div (aux, this->b, op, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div (rop.b, this->a, op, MPFR_RNDU);
mpfr_div (aux, this->b, op, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]/c = [min(a/c,b/c), max(a/c,b/c)]
MPInterval MPInterval::operator/ (double op) const {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_div_d (rop.a, this->a, op, MPFR_RNDD);
mpfr_div_d (aux, this->b, op, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div_d (rop.b, this->a, op, MPFR_RNDU);
mpfr_div_d (aux, this->b, op, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// MISC
// [a,b] ^ -1 = [1/b, 1/a]
MPInterval MPInterval::inverse () const {
MPInterval rop;
// CHECK WHETER 0 IS IN THE INTERVAL
if (this->containsZero ()) {
mpfr_si_div (rop.a, 1, this->b, MPFR_RNDD);
mpfr_si_div (rop.b, 1, this->a, MPFR_RNDU);
} else {
mpfr_set_nan (rop.a);
mpfr_set_nan (rop.b);
}
return rop;
}
// CHECK WHETER 0 IS IN THE INTERVAL
int MPInterval::containsZero () const {
if (mpfr_cmp_si (this->a, 0) <= 0 && mpfr_cmp_si (this->b, 0) >= 0)
return 1;
return 0;
}
// CHECK WHETER A VALUE IS IN THE INTERVAL
int MPInterval::contains (double op) const {
if (mpfr_cmp_d (this->a, op) <= 0 && mpfr_cmp_d (this->b, op) >= 0)
return 1;
return 0;
}
// CHECK WHETER A VALUE IS IN THE INTERVAL
int MPInterval::contains (const mpfr_t op) const {
if (mpfr_cmp (this->a, op) <= 0 && mpfr_cmp (this->b, op) >= 0)
return 1;
return 0;
}
// CHECKS WHETER THE INTERVAL [a,b] IS SUBSET OF ANOTHER [c,d].
// c<a<b<d
int MPInterval::subset (const MPInterval &op) const {
if (mpfr_cmp (this->a, op.a) > 0 && mpfr_cmp (this->b, op.b) < 0)
return 1;
return 0;
}
// CHECKS WHETER THE INTERVAL [a,b] IS SUBSET OF ANOTHER [c,d].
// c<a<b<d
int MPInterval::subset (const Interval &op) const {
if (mpfr_cmp_d (this->a, op.a) > 0 && mpfr_cmp_d (this->b, op.b) < 0)
return 1;
return 0;
}
// EXTERNAL FUNCTIONS
// OVERLOAD OUTPUT STREAM
std::ostream & operator<< (std::ostream &output, const MPInterval &op) {
mpfr_exp_t exponent;
char *string = mpfr_get_str (NULL, &exponent, 10, 0, op.a, MPFR_RNDD);
if (mpfr_signbit (op.a) != 0)
output << "[-" << string[1] << "." << string+2 << "e" << exponent-1 << ", ";
else
output << "[" << string[0] << "." << string+1 << "e" << exponent-1 << ", ";
mpfr_free_str (string);
string = mpfr_get_str (NULL, &exponent, 10, 0, op.b, MPFR_RNDU);
if (mpfr_signbit (op.b) != 0)
output << "-" << string[1] << "." << string+2 << "e" << exponent-1 << "]";
else
output << string[0] << "." << string+1 << "e" << exponent-1 << "]";
mpfr_free_str (string);
return output;
}
// c + [a,b] = [a+c, b+c] = [a,b] + c
MPInterval operator+ (double op1, const MPInterval &op2) {
return op2 + op1;
}
// c + [a,b] = [a+c, b+c] = [a,b] + c
MPInterval operator+ (const mpfr_t op1, const MPInterval &op2) {
return op2 + op1;
}
// [c,d] + [a,b] = [a+c, b+c] = [a,b] + [c,d]
MPInterval operator+ (const Interval &op1, const MPInterval &op2) {
return op2 + op1;
}
// c - [a,b] = [c-b, c-a]
MPInterval operator- (double op1, const MPInterval &op2) {
MPInterval rop;
mpfr_d_sub (rop.a, op1, op2.b, MPFR_RNDD);
mpfr_d_sub (rop.b, op1, op2.a, MPFR_RNDU);
return rop;
}
// c - [a,b] = [c-b, c-a]
MPInterval operator- (const mpfr_t op1, const MPInterval &op2) {
MPInterval rop;
mpfr_sub (rop.a, op1, op2.b, MPFR_RNDD);
mpfr_sub (rop.b, op1, op2.a, MPFR_RNDU);
return rop;
}
// [c,d]- [a,b] = [c-b, d-a]
MPInterval operator- (const Interval &op1, const MPInterval &op2) {
MPInterval rop;
mpfr_d_sub (rop.a, op1.a, op2.b, MPFR_RNDD);
mpfr_d_sub (rop.b, op1.b, op2.a, MPFR_RNDU);
return rop;
}
// c*[a,b] = [a,b]*c
MPInterval operator* (double op1, const MPInterval &op2) {
return op2 * op1;
}
// c*[a,b] = [a,b]*c
MPInterval operator* (const mpfr_t op1, const MPInterval &op2) {
return op2 * op1;
}
// [c,d] * [a,b] = [a,b] * [c,d]
MPInterval operator* (const Interval &op1, const MPInterval &op2) {
return op2 * op1;
}
// c / [a,b] = [min (c/a, c/b), max (c/a, c/b)]
MPInterval operator/ (double op1, const MPInterval &op2) {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_d_div (rop.a, op1, op2.a, MPFR_RNDD);
mpfr_d_div (aux, op1, op2.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_d_div (rop.b, op1, op2.a, MPFR_RNDU);
mpfr_d_div (aux, op1, op2.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// c / [a,b] = [min (c/a, c/b), max (c/a, c/b)]
MPInterval operator/ (const mpfr_t op1, const MPInterval &op2) {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_div (rop.a, op1, op2.a, MPFR_RNDD);
mpfr_div (aux, op1, op2.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_div (rop.b, op1, op2.a, MPFR_RNDU);
mpfr_div (aux, op1, op2.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}
// [a,b]/[c,d] = [min(a/c,a/d,b/c,b/d), max(a/c,a/d,b/c,b/d)]
MPInterval operator/ (const Interval &op1, const MPInterval &op2) {
mpfr_t aux;
mpfr_init (aux);
MPInterval rop;
mpfr_d_div (rop.a, op1.a, op2.a, MPFR_RNDD);
mpfr_d_div (aux, op1.a, op2.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_d_div (aux, op1.b, op2.a, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_d_div (aux, op1.b, op2.b, MPFR_RNDD);
mpfr_min (rop.a, rop.a, aux, MPFR_RNDD);
mpfr_d_div (rop.b, op1.a, op2.a, MPFR_RNDU);
mpfr_d_div (aux, op1.a, op2.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_d_div (aux, op1.b, op2.a, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_d_div (aux, op1.b, op2.b, MPFR_RNDU);
mpfr_max (rop.b, rop.b, aux, MPFR_RNDU);
mpfr_clear (aux);
return rop;
}