SIROCCO2/lib/mp_icomplex.cpp
2017-02-25 13:37:27 +01:00

484 lines
14 KiB
C++

#include "mp_icomplex.hpp"
// CONSTRUCTORS
MPIComplex::MPIComplex (double op)
: r (op), i (0.0) {}
MPIComplex::MPIComplex (double op1, double op2, double op3, double op4)
: r (op1, op2), i (op3, op4) {}
MPIComplex::MPIComplex (const mpfr_t op)
: r (op), i (0.0) {}
MPIComplex::MPIComplex (const MPComplex &op)
: r (op.r), i (op.i) {}
MPIComplex::MPIComplex (const mpfr_t op1, const mpfr_t op2, const mpfr_t op3, const mpfr_t op4)
: r (op1, op2), i (op3, op4) {}
MPIComplex::MPIComplex (const Interval &op1, const Interval &op2)
: r (op1), i (op2) {}
MPIComplex::MPIComplex (const MPInterval &op1, const MPInterval &op2)
: r (op1), i (op2) {}
MPIComplex::MPIComplex (const IComplex &op)
: r (op.r), i (op.i) {}
// COPY CONSTRUCTOR
MPIComplex::MPIComplex (const MPIComplex &op)
: r (op.r), i (op.i) {}
MPIComplex::~MPIComplex () {}
// ASSIGNMENT
MPIComplex & MPIComplex::operator= (const MPIComplex &op) {
// CHECK WHETER WE ARE ASIGNING SOMETHING OVER ITSELF
if (this == &op) return (*this);
// UPDATE ELEMENTS
this->r = op.r; this->i = op.i;
return (*this);
}
MPIComplex & MPIComplex::operator= (const IComplex &op) {
// UPDATE ELEMENTS
this->r = op.r; this->i = op.i;
return (*this);
}
MPIComplex & MPIComplex::operator= (const MPInterval &op) {
// UPDATE ELEMENTS
this->r = op; this->i = 0.0;
return (*this);
}
MPIComplex & MPIComplex::operator= (const Interval &op) {
// UPDATE ELEMENTS
this->r = op; this->i = 0.0;
return (*this);
}
MPIComplex & MPIComplex::operator= (const mpfr_t op) {
// UPDATE ELEMENTS
this->r = op; this->i = 0.0;
return (*this);
}
MPIComplex & MPIComplex::operator= (double op) {
// UPDATE ELEMENTS
this->r = op; this->i = 0.0;
return (*this);
}
// // COMPARISON
int MPIComplex::operator== (double op) const {
return (this->r == op) && (this->i == 0);
}
int MPIComplex::operator== (const std::complex<double> &op) const {
return (this->r == op.real() && this->i == op.imag ());
}
int MPIComplex::operator== (const Interval &op) const {
return (this->r == op) && (this->i == 0);
}
int MPIComplex::operator== (const MPInterval &op) const {
return (this->r == op) && (this->i == 0);
}
int MPIComplex::operator== (const MPIComplex &op) const {
return (this->r == op.r) && (this->i == op.i);
}
int MPIComplex::operator!= (double op) const {
return (this->r != op) || (this->i != 0);
}
int MPIComplex::operator!= (const std::complex<double> &op) const {
return (this->r != op.real() || this->i != op.imag ());
}
int MPIComplex::operator!= (const Interval &op) const {
return (this->r != op) || (this->i != 0);
}
int MPIComplex::operator!= (const MPInterval &op) const {
return (this->r != op) || (this->i != 0);
}
int MPIComplex::operator!= (const MPIComplex &op) const {
return (this->r != op.r) || (this->i != op.i);
}
// // ARITHMETIC
// A INTERVAL REAL PART
// B INTERNAL IMAG PART
// (A + iB) + (C + iD) = (A+C) + i(B+D)
MPIComplex MPIComplex::operator+ (const MPIComplex &op) const {
return MPIComplex (this->r + op.r, this->i + op.i);
}
// (A + iB) + (C + iD) = (A+C) + i(B+D)
MPIComplex MPIComplex::operator+ (const IComplex &op) const {
return MPIComplex (this->r + op.r, this->i + op.i);
}
// (A + iB) + C = (A+C) + iB
MPIComplex MPIComplex::operator+ (const MPInterval &op) const {
return MPIComplex (this->r + op, this->i);
}
// (A + iB) + C = (A+C) + iB
MPIComplex MPIComplex::operator+ (const Interval &op) const {
return MPIComplex (this->r + op, this->i);
}
// (A + iB) + C = (A+C) + iB
MPIComplex MPIComplex::operator+ (const mpfr_t op) const {
return MPIComplex (this->r + op, this->i);
}
// (A + iB) + C = (A+C) + iB
MPIComplex MPIComplex::operator+ (double op) const {
return MPIComplex (this->r + op, this->i);
}
// -(A + iB) = (-A) + i(-B)
MPIComplex MPIComplex::operator- () const {
return MPIComplex (-(this->r), -(this->i));
}
// (A + iB) - (C + iD) = (A-C) + i(B-D)
MPIComplex MPIComplex::operator- (const MPIComplex &op) const {
return MPIComplex (this->r - op.r, this->i - op.i);
}
// (A + iB) - (C + iD) = (A-C) + i(B-D)
MPIComplex MPIComplex::operator- (const IComplex &op) const {
return MPIComplex (this->r - op.r, this->i - op.i);
}
// (A + iB) - C = (A-C) + iB
MPIComplex MPIComplex::operator- (const MPInterval &op) const {
return MPIComplex (this->r - op, this->i);
}
// (A + iB) - C = (A-C) + iB
MPIComplex MPIComplex::operator- (const Interval &op) const {
return MPIComplex (this->r - op, this->i);
}
// (A + iB) - C = (A-C) + iB
MPIComplex MPIComplex::operator- (const mpfr_t op) const {
return MPIComplex (this->r - op, this->i);
}
// (A + iB) - C = (A-C) + iB
MPIComplex MPIComplex::operator- (double op) const {
return MPIComplex (this->r - op, this->i);
}
// (A + iB) * (C + iD) = (A*C - B*D) + i(A*D + B*C)
MPIComplex MPIComplex::operator* (const MPIComplex &op) const {
return MPIComplex (this->r * op.r - this->i * op.i,
this->r * op.i + this->i * op.r);
}
// (A + iB) * (C + iD) = (A*C - B*D) + i(A*D + B*C)
MPIComplex MPIComplex::operator* (const IComplex &op) const {
return MPIComplex (this->r * op.r - this->i * op.i,
this->r * op.i + this->i * op.r);
}
// (A + iB) * C = (A*C) + i(B*C)
MPIComplex MPIComplex::operator* (const MPInterval &op) const {
return MPIComplex (this->r * op, this->i * op);
}
// (A + iB) * C = (A*C) + i(B*C)
MPIComplex MPIComplex::operator* (const Interval &op) const {
return MPIComplex (this->r * op, this->i * op);
}
// (A + iB) * C = (A*C) + i(B*C)
MPIComplex MPIComplex::operator* (const mpfr_t op) const {
return MPIComplex (this->r * op, this->i * op);
}
// (A + iB) * C = (A*C) + i(B*C)
MPIComplex MPIComplex::operator* (double op) const {
return MPIComplex (this->r * op, this->i * op);
}
MPIComplex MPIComplex::operator/ (const MPIComplex &op) const {
return (*this) * (op.inverse ());
}
MPIComplex MPIComplex::operator/ (const IComplex &op) const {
return (*this) * (op.inverse ());
}
MPIComplex MPIComplex::operator/ (const MPInterval &op) const {
return (*this) * (op.inverse ());
}
MPIComplex MPIComplex::operator/ (const Interval &op) const {
return (*this) * (op.inverse ());
}
MPIComplex MPIComplex::operator/ (const mpfr_t op) const {
return (*this) * (MPIComplex(op).inverse ());
}
MPIComplex MPIComplex::operator/ (double op) const {
return (*this) * (IComplex(op).inverse ());
}
// // MISC
MPIComplex MPIComplex::inverse () const {
if (this->containsZero()) {
mpfr_t aux;
mpfr_init (aux);
mpfr_set_nan (aux);
MPIComplex rop (aux);
mpfr_clear (aux);
return rop;
}
MPIComplex inv_edge[4], rop;
inv_edge[0] = inverse_horizontal (this->r.a, this->r.b, this->i.a);
inv_edge[1] = inverse_horizontal (this->r.a, this->r.b, this->i.b);
inv_edge[2] = inverse_vertical (this->i.a, this->i.b, this->r.a);
inv_edge[3] = inverse_vertical (this->i.a, this->i.b, this->r.b);
mpfr_min (rop.r.a, inv_edge[0].r.a, inv_edge[1].r.a, MPFR_RNDD);
mpfr_min (rop.r.a, rop.r.a, inv_edge[2].r.a, MPFR_RNDD);
mpfr_min (rop.r.a, rop.r.a, inv_edge[3].r.a, MPFR_RNDD);
mpfr_max (rop.r.b, inv_edge[0].r.b, inv_edge[1].r.b, MPFR_RNDU);
mpfr_max (rop.r.b, rop.r.b, inv_edge[2].r.b, MPFR_RNDU);
mpfr_max (rop.r.b, rop.r.b, inv_edge[3].r.b, MPFR_RNDU);
mpfr_min (rop.i.a, inv_edge[0].i.a, inv_edge[1].i.a, MPFR_RNDD);
mpfr_min (rop.i.a, rop.i.a, inv_edge[2].i.a, MPFR_RNDD);
mpfr_min (rop.i.a, rop.i.a, inv_edge[3].i.a, MPFR_RNDD);
mpfr_max (rop.i.b, inv_edge[0].i.b, inv_edge[1].i.b, MPFR_RNDU);
mpfr_max (rop.i.b, rop.i.b, inv_edge[2].i.b, MPFR_RNDU);
mpfr_max (rop.i.b, rop.i.b, inv_edge[3].i.b, MPFR_RNDU);
return rop;
}
int MPIComplex::containsZero () const {
return ((this->r).containsZero () && (this->i).containsZero());
}
int MPIComplex::contains (double op) const {
return ((this->r).contains (op) && (this->i).contains(op));
}
int MPIComplex::contains (const mpfr_t op) const {
return ((this->r).contains (op) && (this->i).contains(op));
}
int MPIComplex::subset (const MPIComplex &op) const {
return (this->r).subset (op.r) && (this->i).subset (op.i);
}
// // NON MEMBER FUNCTIONS
std::ostream & operator<< (std::ostream &output, const MPIComplex &op) {
output << op.r << " + i" << op.i;
return output;
}
MPIComplex operator+ (const IComplex &op1, const MPIComplex &op2) {
return MPIComplex (op1.r + op2.r, op1.i + op2.i);
}
MPIComplex operator+ (const MPInterval &op1, const MPIComplex &op2) {
return MPIComplex (op2.r, op1 + op2.i);
}
MPIComplex operator+ (const Interval &op1, const MPIComplex &op2) {
return MPIComplex (op1 + op2.r, op2.i);
}
MPIComplex operator+ (const mpfr_t op1, const MPIComplex &op2) {
return MPIComplex (op1 + op2.r, op2.i);
}
MPIComplex operator+ (double op1, const MPIComplex &op2) {
return MPIComplex (op1 + op2.r, op2.i);
}
MPIComplex operator- (const IComplex &op1, const MPIComplex &op2) {
return MPIComplex (op1.r - op2.r, op1.i - op2.i);
}
MPIComplex operator- (const MPInterval &op1, const MPIComplex &op2) {
return MPIComplex (op1 - op2.r, -op2.i);
}
MPIComplex operator- (const Interval &op1, const MPIComplex &op2) {
return MPIComplex (op1 - op2.r, -op2.i);
}
MPIComplex operator- (const mpfr_t op1, const MPIComplex &op2) {
return MPIComplex (op1 - op2.r, -op2.i);
}
MPIComplex operator- (double op1, const MPIComplex &op2) {
return MPIComplex (op1 - op2.r, -op2.i);
}
MPIComplex operator* (const IComplex &op1, const MPIComplex &op2) {
return MPIComplex (op1.r * op2.r - op1.i * op2.i,
op1.r * op2.i + op1.i * op2.r);
}
MPIComplex operator* (const MPInterval &op1, const MPIComplex &op2) {
return MPIComplex (op1 * op2.r, op1 * op2.i);
}
MPIComplex operator* (const Interval &op1, const MPIComplex &op2) {
return MPIComplex (op1 * op2.r, op1 * op2.i);
}
MPIComplex operator* (const mpfr_t op1, const MPIComplex &op2) {
return MPIComplex (op1 * op2.r, op1 * op2.i);
}
MPIComplex operator* (double op1, const MPIComplex &op2) {
return MPIComplex (op1 * op2.r, op1 * op2.i);
}
MPIComplex operator/ (const IComplex &op1, const MPIComplex &op2) {
return op1 * (op2.inverse ());
}
MPIComplex operator/ (const MPInterval &op1, const MPIComplex &op2) {
return op1 * (op2.inverse ());
}
MPIComplex operator/ (const Interval &op1, const MPIComplex &op2) {
return op1 * (op2.inverse ());
}
MPIComplex operator/ (const mpfr_t op1, const MPIComplex &op2) {
return op1 * (op2.inverse ());
}
MPIComplex operator/ (double op1, const MPIComplex &op2) {
return op1 * (op2.inverse ());
}
// // MISCELLANEOUS FUNCTIONS FOR INVERT COMPLEX INTERVALS
// returns inverse of horizontal segment [a,b] + ci
MPIComplex inverse_horizontal (const mpfr_t a, const mpfr_t b, const mpfr_t c) {
MPIComplex rop;
mpfr_t aux;
mpfr_init (aux);
// case c = 0
if (mpfr_cmp_si (c, 0) == 0) {
if (mpfr_cmp_si (a, 0) < 0 && mpfr_cmp_si (b, 0) > 0) {
mpfr_set_nan (rop.r.a);
mpfr_set_nan (rop.r.b);
mpfr_set_nan (rop.i.a);
mpfr_set_nan (rop.i.b);
} else {
mpfr_si_div (rop.r.a, 1, b, MPFR_RNDD);
mpfr_si_div (rop.r.b, 1, a, MPFR_RNDU);
mpfr_set_si (rop.i.a, 0, MPFR_RNDD);
mpfr_set_si (rop.i.b, 0, MPFR_RNDU);
}
// case c > 0
} else if (mpfr_cmp_si (c, 0) > 0) {
// case a<0<b
if (mpfr_cmp_si (a, 0) < 0 && mpfr_cmp_si (b, 0) > 0) {
mpfr_si_div (rop.i.a, -1, c, MPFR_RNDD);
if (mpfr_cmpabs (b, a) > 0)
g (rop.i.b, b, c, MPFR_RNDU);
else
g (rop.i.b, a, c, MPFR_RNDU);
if (mpfr_cmpabs (a, c) > 0) {
mpfr_mul_si (aux, c, 2, MPFR_RNDD);
mpfr_si_div (rop.r.a, -1, aux, MPFR_RNDD);
} else
f (rop.r.a, a, c, MPFR_RNDD);
if (mpfr_cmp (c, b) < 0) {
mpfr_mul_si (aux, c, 2, MPFR_RNDU);
mpfr_si_div (rop.r.b, 1, aux, MPFR_RNDU);
} else {
f (rop.r.b, b, c, MPFR_RNDU);
}
}
// case 0<=a<b
else if (mpfr_cmp_si (a, 0) >= 0) {
g (rop.i.a, a, c, MPFR_RNDD);
g (rop.i.b, b, c, MPFR_RNDU);
f (aux, a, c, MPFR_RNDD);
f (rop.r.a, b, c, MPFR_RNDD);
mpfr_min (rop.r.a, rop.r.a, aux, MPFR_RNDD);
if (mpfr_cmp (b, c) < 0) {
f (rop.r.b, b, c, MPFR_RNDU);
} else if (mpfr_cmp (c, a) < 0) {
f (rop.r.b, a, c, MPFR_RNDU);
} else {
mpfr_mul_si (rop.r.b, c, 2, MPFR_RNDU);
mpfr_si_div (rop.r.b, 1, rop.r.b, MPFR_RNDU);
}
}
// case a<b<=0
else if (mpfr_cmp_si (b, 0) <= 0) {
g (rop.i.a, b, c, MPFR_RNDD);
g (rop.i.b, a, c, MPFR_RNDU);
f (aux, a, c, MPFR_RNDU);
f (rop.r.b, b, c, MPFR_RNDU);
mpfr_max (rop.r.b, rop.r.b, aux, MPFR_RNDU);
if (mpfr_cmpabs (c, a) > 0) {
f (rop.r.a, a, c, MPFR_RNDD);
} else if (mpfr_cmpabs (b, c) > 0) {
f (rop.r.a, b, c, MPFR_RNDD);
} else {
mpfr_mul_si (rop.r.a, c, 2, MPFR_RNDD);
mpfr_si_div (rop.r.a, -1, rop.r.a, MPFR_RNDD);
}
}
// case c < 0
} else {
mpfr_neg (aux, c, MPFR_RNDN); // ???
rop = inverse_horizontal (a, b, aux);
rop.i = -rop.i;
}
mpfr_clear (aux);
return rop;
}
// returns inverse of verticla segment c + [a,b]i
MPIComplex inverse_vertical (const mpfr_t a, const mpfr_t b, const mpfr_t c) {
mpfr_t aux1, aux2;
mpfr_inits (aux1, aux2, NULL);
mpfr_neg (aux1, b, MPFR_RNDD);
mpfr_neg (aux2, a, MPFR_RNDU);
MPIComplex rop;
rop = inverse_horizontal (aux1, aux2, c);
MPInterval aux (rop.i);
rop.i = rop.r;
rop.r = -aux;
mpfr_clears (aux1, aux2, NULL);
return rop;
}
void f (mpfr_t rop, const mpfr_t x, const mpfr_t c, mpfr_rnd_t roundMode) {
mpfr_t aux;
mpfr_init(aux);
mpfr_mul (aux, c, c, roundMode);
mpfr_mul (rop, x, x, roundMode);
mpfr_add (rop, rop, aux, roundMode);
mpfr_div (rop, x, rop, roundMode);
mpfr_clear (aux);
}
void g (mpfr_t rop, const mpfr_t x, const mpfr_t c, mpfr_rnd_t roundMode) {
mpfr_t aux;
mpfr_init (aux);
mpfr_mul (aux, c, c, roundMode);
mpfr_mul (rop, x, x, roundMode);
mpfr_add (rop, rop, aux, roundMode);
mpfr_neg (aux, c, roundMode);
mpfr_div (rop, aux, rop, roundMode);
mpfr_clear (aux);
}