Shinya Kitaoka 810553
#pragma once
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef T_INTERVAL_INCLUDED
Toshihiro Shimizu 890ddd
#define T_INTERVAL_INCLUDED
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <assert.h></assert.h>
Toshihiro Shimizu 890ddd
#include <limits.h></limits.h>
Toshihiro Shimizu 890ddd
#include "tcommon.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef DVAPI
Toshihiro Shimizu 890ddd
#undef DVVAR
Toshihiro Shimizu 890ddd
#ifdef TNZCORE_EXPORTS
Toshihiro Shimizu 890ddd
#define DVAPI DV_EXPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_EXPORT_VAR
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define DVAPI DV_IMPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_IMPORT_VAR
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  class TInterval implementa "Interval Arithmetic" (non vengono computati gli
Toshihiro Shimizu 890ddd
//  errori macchina):
Shinya Kitaoka 120a6e
//  TInterval(min, max) (min <= max) rapresenta l'intervallo reale chiuso [min,
Shinya Kitaoka 120a6e
//  max];
Toshihiro Shimizu 890ddd
//  per m_min == m_max si ottiene l'algebra dei reali;
Toshihiro Shimizu 890ddd
//  TInterval (m_min = 1, m_max = -1) rappresenta l'intervallo vuoto
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TInterval {
Shinya Kitaoka 120a6e
  double m_min, m_max;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  //  costruisce l'intervallo vuoto
Shinya Kitaoka 120a6e
  //  TInterval (m_min = 1, m_max = -1) rappresenta l'intervallo vuoto
Shinya Kitaoka 120a6e
  TInterval() : m_min(1), m_max(-1) {}
Toshihiro Shimizu 890ddd
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  //  costruisce gli intervalli degeneri [x, x] che rappresentano i reali
Shinya Kitaoka 120a6e
  TInterval(double x) : m_min(x), m_max(x) {}
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  TInterval(double min, double max) {
Shinya Kitaoka 120a6e
    assert(min <= max);  //  non vuoto
Shinya Kitaoka 120a6e
    m_min = min;
Shinya Kitaoka 120a6e
    m_max = max;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  TInterval(const TInterval &w) {
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max ||
Shinya Kitaoka 120a6e
           (w.m_min == 1 && w.m_max == -1));  //  intervallo vuoto
Shinya Kitaoka 120a6e
    m_min = w.m_min;
Shinya Kitaoka 120a6e
    m_max = w.m_max;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval &operator=(const TInterval &w) {
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max ||
Shinya Kitaoka 120a6e
           (w.m_min == 1 && w.m_max == -1));  //  intervallo vuoto
Shinya Kitaoka 120a6e
    m_min = w.m_min;
Shinya Kitaoka 120a6e
    m_max = w.m_max;
Shinya Kitaoka 120a6e
    return *this;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval operator+() const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return *this;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval operator-() const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return TInterval(-m_max, -m_min);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval operator+(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);      //  non vuoto
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return TInterval(m_min + w.m_min, m_max + w.m_max);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval operator-(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);      //  non vuoto
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return TInterval(m_min - w.m_max, m_max - w.m_min);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval operator*(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);      //  non vuoto
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    double value[4];
Shinya Kitaoka 120a6e
    value[0]        = m_min * w.m_min;
Shinya Kitaoka 120a6e
    value[1]        = m_min * w.m_max;
Shinya Kitaoka 120a6e
    value[2]        = m_max * w.m_min;
Shinya Kitaoka 120a6e
    value[3]        = m_max * w.m_max;
Shinya Kitaoka 120a6e
    double minValue = value[0];
Shinya Kitaoka 120a6e
    double maxValue = value[0];
Shinya Kitaoka 120a6e
    int i           = 1;
Shinya Kitaoka 120a6e
    for (i = 1; i <= 3; ++i) {
Shinya Kitaoka 120a6e
      if (value[i] < minValue) minValue = value[i];
Shinya Kitaoka 120a6e
      if (value[i] > maxValue) maxValue = value[i];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return TInterval(minValue, maxValue);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline TInterval operator/(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);      //  non vuoto
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    assert((0 < w.m_min && 0 < w.m_max) ||
Shinya Kitaoka 120a6e
           (0 > w.m_min && 0 > w.m_max));  //  divisore non nullo
Shinya Kitaoka 120a6e
    double value[4];
Shinya Kitaoka 120a6e
    value[0]        = m_min / w.m_min;
Shinya Kitaoka 120a6e
    value[1]        = m_min / w.m_max;
Shinya Kitaoka 120a6e
    value[2]        = m_max / w.m_min;
Shinya Kitaoka 120a6e
    value[3]        = m_max / w.m_max;
Shinya Kitaoka 120a6e
    double minValue = value[0];
Shinya Kitaoka 120a6e
    double maxValue = value[0];
Shinya Kitaoka 120a6e
    int i           = 1;
Shinya Kitaoka 120a6e
    for (i = 1; i <= 3; ++i) {
Shinya Kitaoka 120a6e
      if (value[i] < minValue) minValue = value[i];
Shinya Kitaoka 120a6e
      if (value[i] > maxValue) maxValue = value[i];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return TInterval(minValue, maxValue);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool operator==(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max ||
Shinya Kitaoka 120a6e
           (w.m_min == 1 && w.m_max == -1));  //  intervallo vuoto
Shinya Kitaoka 120a6e
    return (m_min == w.m_min && m_max == w.m_max);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  /*  la definizione e' discutibile...
Shinya Kitaoka 120a6e
inline bool operator!=(const TInterval &w) const
Shinya Kitaoka 120a6e
{return (m_min != w.m_min  ||  m_max != w.m_max);}
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool operator>(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);      //  non vuoto
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return (m_min > w.m_max);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool operator<(const TInterval &w) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);      //  non vuoto
Shinya Kitaoka 120a6e
    assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return (m_max < w.m_min);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  /*  la definizione e' discutibile...
Shinya Kitaoka 120a6e
//  A >= B
Shinya Kitaoka 120a6e
inline bool operator>=(const TInterval &w) const {
Shinya Kitaoka 120a6e
assert (m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
assert (w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
return (m_min >= w.m_min && m_max >= w.m_max);}
Shinya Kitaoka 120a6e
//-----------------------------------------------------
Shinya Kitaoka 120a6e
//  A <= B
Shinya Kitaoka 120a6e
inline bool operator<=(const TInterval &w) const {
Shinya Kitaoka 120a6e
assert (m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
assert (w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
return (m_min <= w.m_min  && m_max <= w.m_max);}
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline void setMin(double min) {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    assert(min <= m_max);    //  non vuoto dopo setMin
Shinya Kitaoka 120a6e
    m_min = min;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline void setMax(double max) {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    assert(m_min <= max);    //  non vuoto dopo setMax
Shinya Kitaoka 120a6e
    m_max = max;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline double getMin() const {
Shinya Kitaoka 120a6e
    //  isEmpty() => return 1
Shinya Kitaoka 120a6e
    return m_min;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline double getMax() const {
Shinya Kitaoka 120a6e
    //  isEmpty() => return -1
Shinya Kitaoka 120a6e
    return m_max;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline double getLength() const {
Shinya Kitaoka 120a6e
    return m_max - m_min;
Shinya Kitaoka 120a6e
  }  //  isEmpty() => (getLength() < 0)
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline double getCenter() const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return (m_max + m_min) / 2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline double getRadius() const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max);  //  non vuoto
Shinya Kitaoka 120a6e
    return (m_max - m_min) / 2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool isEmpty() const {
Shinya Kitaoka 120a6e
    //  TInterval (m_min = 1, m_max = -1) rappresenta l'intervallo vuoto
Shinya Kitaoka 120a6e
    assert(m_min <= m_max || (m_min == 1 && m_max == -1));  //  intervallo vuoto
Shinya Kitaoka 120a6e
    return (m_min > m_max);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool isProper() const {
Shinya Kitaoka 120a6e
    //  isProper() <=> !isEmpty() && m_min < m_max (cioe' non degenere)
Shinya Kitaoka 120a6e
    //  TInterval (m_min = 1, m_max = -1) rappresenta l'intervallo vuoto
Shinya Kitaoka 120a6e
    assert(m_min <= m_max || (m_min == 1 && m_max == -1));  //  intervallo vuoto
Shinya Kitaoka 120a6e
    return (m_min < m_max);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool contain(double t) const {
Shinya Kitaoka 120a6e
    assert(m_min <= m_max || (m_min == 1 && m_max == -1));  //  intervallo vuoto
Shinya Kitaoka 120a6e
    return (m_min <= t && t <= m_max);
Shinya Kitaoka 120a6e
  }  //  isEmpty() => return false
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool include(const TInterval &interval) const {
Shinya Kitaoka 120a6e
    if (interval.isEmpty())
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    else if (isEmpty())
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      assert(!interval.isEmpty() && !isEmpty());
Shinya Kitaoka 120a6e
      return (m_min <= interval.m_min && interval.m_max <= m_max);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  inline bool isIncluded(const TInterval &interval) const {
Shinya Kitaoka 120a6e
    if (isEmpty())
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    else if (interval.isEmpty())
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      assert(!isEmpty() && !interval.isEmpty());
Shinya Kitaoka 120a6e
      return (interval.m_min <= m_min && m_max <= interval.m_max);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //-----------------------------------------------------
Shinya Kitaoka 120a6e
  // Friend helper function declarations
Shinya Kitaoka 120a6e
  friend TInterval operator*(const double s, const TInterval &w);
Shinya Kitaoka 120a6e
  friend TInterval intersection(const TInterval &a, const TInterval &b);
Shinya Kitaoka 120a6e
  friend TInterval square(const TInterval &w);
Shinya Kitaoka 120a6e
  friend TInterval sqrt(const TInterval &w);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Shinya Kitaoka 120a6e
// friend functions
Shinya Kitaoka 120a6e
inline TInterval operator*(const double s, const TInterval &w) {
Shinya Kitaoka 120a6e
  assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
  if (s >= 0)
Shinya Kitaoka 120a6e
    return TInterval(s * w.m_min, s * w.m_max);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return TInterval(s * w.m_max, s * w.m_min);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Shinya Kitaoka 120a6e
inline TInterval square(const TInterval &w) {
Shinya Kitaoka 120a6e
  //  return w^2
Shinya Kitaoka 120a6e
  assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
  double a = w.m_min * w.m_min;
Shinya Kitaoka 120a6e
  double b = w.m_max * w.m_max;
Shinya Kitaoka 120a6e
  if (0 <= w.m_min)
Shinya Kitaoka 120a6e
    return TInterval(a, b);  //  return [m_min^2, m_max^2]
Shinya Kitaoka 120a6e
  else if (w.m_max <= 0)
Shinya Kitaoka 120a6e
    return TInterval(b, a);  //  return [m_max^2, m_min^2]
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    assert(w.m_min < 0 && 0 < w.m_max);
Shinya Kitaoka 120a6e
    return TInterval(0, std::max(a, b));  //  [0, max(w.m_min^2, w.m_max^2)]
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Shinya Kitaoka 120a6e
inline TInterval sqrt(const TInterval &w) {
Shinya Kitaoka 120a6e
  //  return sqrt(w)
Shinya Kitaoka 120a6e
  assert(w.m_min <= w.m_max);  //  non vuoto
Shinya Kitaoka 120a6e
  assert(0 <= w.m_min);
Shinya Kitaoka 120a6e
  return TInterval(sqrt(w.m_min), sqrt(w.m_max));
Shinya Kitaoka 120a6e
}  //  [sqrt(w.m_min), sqrt(w.m_max)]
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Toshihiro Shimizu 890ddd
//  helper function
Shinya Kitaoka 120a6e
inline TInterval intersection(const TInterval &a, const TInterval &b) {
Shinya Kitaoka 120a6e
  //  return a_intersezione_b (insiemistico) se questa e' non vuota, altrimenti
Shinya Kitaoka 120a6e
  //  return TInterval() (intervallo vuoto)
Shinya Kitaoka 120a6e
  double min = std::max(a.m_min, b.m_min);
Shinya Kitaoka 120a6e
  double max = std::min(a.m_max, b.m_max);
Shinya Kitaoka 120a6e
  if (min <= max)  //  a.isEmpty() || b.isEmpty() => (min >= 1 && max <= -1) =>
Shinya Kitaoka 120a6e
                   //  min > max
Shinya Kitaoka 120a6e
    return TInterval(min, max);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return TInterval();  //  intervallo vuoto
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Shinya Kitaoka 120a6e
inline TInterval createTInterval(double center, double radius) {
Shinya Kitaoka 120a6e
  if (radius >= 0)
Shinya Kitaoka 120a6e
    return TInterval(center - radius, center + radius);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return TInterval();  //  intervallo vuoto
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Shinya Kitaoka 120a6e
inline TInterval createErrorTInterval(
Shinya Kitaoka 120a6e
    double center, double minError = (std::numeric_limits<double>::min)()) {</double>
Shinya Kitaoka 120a6e
  //  type double standard IEEE (1 bit segno + 11 bit esponente + 52 bit
Shinya Kitaoka 120a6e
  //  mantissa)
Shinya Kitaoka 120a6e
  //  corrisponde ad almeno 15 decimali significativi.
Shinya Kitaoka 120a6e
  //  minError serve ad assegnare un errore positivo quando center = 0.
Shinya Kitaoka 120a6e
  //  Aumentare 100 volte (da 1e-15 a 1e-13) l'errore relativo serve a
Shinya Kitaoka 120a6e
  //  compensare
Shinya Kitaoka 120a6e
  //  la propagazione degli errori macchina (TInterval non li computa) ed a
Shinya Kitaoka 120a6e
  //  stabilizzare il codice relativamente a processori che potrebbero male
Shinya Kitaoka 120a6e
  //  implementare l'artimetica double standard IEEE.
Shinya Kitaoka 120a6e
  assert(minError >= 0);
Shinya Kitaoka 120a6e
  const double relativeDoubleError = 1e-13;
Shinya Kitaoka 120a6e
  double error = std::max(fabs(center) * relativeDoubleError, minError);
Shinya Kitaoka 120a6e
  return TInterval(center - error, center + error);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  //  __T_INTERVAL_INCLUDED__