00001 #ifndef INTERVAL_HPP__
00002 #define INTERVAL_HPP__
00003
00004 #include "fv_float.h"
00005
00006 namespace FemViewer {
00007 namespace fvmath {
00008 template<typename T>
00009 class Interval
00010 {
00011 public:
00012 Interval() : m_low(1.0), m_high(-1.0)
00013 {}
00014 Interval(const T& v) : m_low(v),m_high(v)
00015 {}
00016 Interval(const T& low, const T& high) :
00017 m_low(low),
00018 m_high(high)
00019 {}
00020 Interval(const Interval& rhs) :
00021 m_low(rhs.m_low),
00022 m_high(rhs.m_high)
00023 {}
00024 ~Interval() {}
00025
00026 Interval& operator=(const Interval& rhs)
00027 {
00028 m_low = rhs.m_low;
00029 m_high = rhs.m_high;
00030 return *this;
00031 }
00032
00033 void Combine(const Interval<T>& rhs)
00034 {
00035 if( rhs.GetLow() < GetLow() ) SetLow(rhs.GetLow());
00036 if( rhs.GetHigh() > GetHigh() ) SetHigh(rhs.GetHigh());
00037 }
00038
00039 const T& GetLow() const { return m_low; }
00040 const T& GetHigh() const { return m_high; }
00041 void SetLow(const T& low) { m_low = low; }
00042 void SetHigh(const T& high) { m_high = high; }
00043 void Set(const T& low, const T& high) { SetLow(low); SetHigh(high); }
00044 bool Contains(const T& value) const { return value >= m_low && value <= m_high; }
00045
00046 bool IsEmpty() const { return m_low > m_high; }
00047 T GetWidth() const { return m_high - m_low; }
00048 T GetMidpoint() const { return (m_low + m_high)*FLOAT_CONVERT(.5); }
00049 T GetMax() const { return fmaxf(fabsf(m_low), fabsf(m_high)); }
00050
00051 void Union(const Interval<T>& rhs)
00052 {
00053 if( !IsEmpty() && !rhs.IsEmpty() )
00054 {
00055 SetLow(fminf(GetLow(), rhs.GetLow()));
00056 SetHigh(fmaxf(GetHigh(), rhs.GetHigh()));
00057 }
00058 else if( IsEmpty() && !rhs.IsEmpty() )
00059 {
00060 (*this) = rhs;
00061 }
00062 }
00063
00064 void operator+=(const Interval<T>& rhs)
00065 {
00066 m_low += rhs.m_low;
00067 m_high += rhs.m_high;
00068 }
00069
00070 private:
00071 T m_low;
00072 T m_high;
00073 };
00074
00075
00076 template< typename T >
00077 bool Subset(const Interval<T>& a, const Interval<T>& b)
00078 {
00079 return b.Contains(a.GetLow()) && b.Contains(a.GetHigh());
00080 }
00081
00082 template<typename T>
00083 Interval<T> fabs(const Interval<T>& rhs)
00084 {
00085 if( rhs.IsEmpty() ) return rhs;
00086 return Interval<T>(fabs(rhs.GetLow()), fabs(rhs.GetHigh()));
00087 }
00088
00089 template<typename T>
00090 Interval<T> operator+(const Interval<T>& lhs, const Interval<T>& rhs)
00091 {
00092 if( lhs.IsEmpty() || rhs.IsEmpty() )
00093 {
00094 return Interval<T>();
00095 }
00096
00097 return Interval<T>(lhs.GetLow() + rhs.GetLow(), lhs.GetHigh() + rhs.GetHigh());
00098 }
00099
00100
00101 template<typename T>
00102 Interval<T> operator/(const Interval<T>& lhs, const Interval<T>& rhs)
00103 {
00104 if( lhs.IsEmpty() || rhs.IsEmpty() )
00105 {
00106 return Interval<T>();
00107 }
00108
00109 T a = lhs.GetLow();
00110 T b = lhs.GetHigh();
00111 T c = rhs.GetLow();
00112 T d = rhs.GetHigh();
00113 T v0 = a/c;
00114 T v1 = a/d;
00115 T v2 = b/c;
00116 T v3 = b/d;
00117
00118 Interval<T> result(fminf(fminf(fminf(v0, v1), v2), v3), fmaxf(fmaxf(fmaxf(v0, v1), v2), v3));
00119 return result;
00120 }
00121
00122 template<typename T>
00123 Interval<T> operator/(const Interval<T>& lhs, const double& rhs)
00124 {
00125 if( lhs.IsEmpty() )
00126 {
00127 return Interval<T>();
00128 }
00129 Interval<T> newRhs(rhs, rhs);
00130 return lhs/newRhs;
00131 }
00132
00133 template<typename T>
00134 Interval<T> operator/(const Interval<T>& lhs, const float& rhs)
00135 {
00136 if( lhs.IsEmpty() )
00137 {
00138 return Interval<T>();
00139 }
00140 Interval<T> newRhs(rhs, rhs);
00141 return lhs/newRhs;
00142 }
00143
00144
00145 template<typename T>
00146 Interval<T> operator/(const double& lhs, const Interval<T>& rhs)
00147 {
00148 if( rhs.IsEmpty() )
00149 {
00150 return Interval<T>();
00151 }
00152 Interval<T> newLhs(lhs, lhs);
00153 return newLhs/rhs;
00154
00155 }
00156
00157 template<typename T>
00158 Interval<T> operator/(const float& lhs, const Interval<T>& rhs)
00159 {
00160 if( rhs.IsEmpty() )
00161 {
00162 return Interval<T>();
00163 }
00164 Interval<T> newLhs(lhs, lhs);
00165 return newLhs/rhs;
00166
00167 }
00168
00169 template<typename T>
00170 void Divide(const Interval<T>& lhs, const Interval<T>& rhs, Interval<T>& out1, Interval<T>& out2)
00171 {
00172 out1 = Interval<T>();
00173 out2 = Interval<T>();
00174
00175 if( lhs.IsEmpty() || rhs.IsEmpty() )
00176 {
00177 return;
00178 }
00179
00180 if( rhs.Contains(0.0) )
00181 {
00182 if( rhs.GetLow() < 0.0 &&
00183 rhs.GetHigh() > 0.0 )
00184 {
00185 Interval<double> rhs1(-FV_FLOAT_MAX,1.0/rhs.GetLow());
00186 out1 = lhs*rhs1;
00187
00188 Interval<double> rhs2(1.0/rhs.GetHigh(),FV_FLOAT_MAX);
00189 out2 = lhs*rhs2;
00190 }
00191 else if( rhs.GetLow() == 0.0 )
00192 {
00193 Interval<double> rhs2(1.0/rhs.GetHigh(),FV_FLOAT_MAX);
00194 out1 = lhs*rhs2;
00195 }
00196 else
00197 {
00198 Interval<double> rhs1(-FV_FLOAT_MAX,1.0/rhs.GetLow());
00199 out1 = lhs*rhs1;
00200 }
00201 }
00202 else
00203 {
00204 out1 = lhs/rhs;
00205 }
00206 }
00207
00208 template<typename T>
00209 void Divide(const T& lhs, const Interval<T>& rhs, Interval<T>& out1, Interval<T>& out2)
00210 {
00211 Interval<T> newLhs(lhs, lhs);
00212 Divide(newLhs, rhs, out1, out2);
00213 }
00214
00215 template<typename T>
00216 void Divide(const Interval<T>& lhs,const T& rhs, Interval<T>& out1, Interval<T>& out2)
00217 {
00218 Interval<T> newRhs(rhs, rhs);
00219 Divide(lhs, newRhs, out1, out2);
00220 }
00221
00222 template<typename T>
00223 Interval<T> operator+(const Interval<T>& lhs, const double& rhs)
00224 {
00225 if( lhs.IsEmpty() )
00226 {
00227 return Interval<T>();
00228 }
00229
00230 return Interval<T>(lhs.GetLow() + rhs, lhs.GetHigh() + rhs);
00231 }
00232
00233 template<typename T>
00234 Interval<T> operator+(const double& lhs, const Interval<T>& rhs)
00235 {
00236 if( rhs.IsEmpty() )
00237 {
00238 return Interval<T>();
00239 }
00240 return Interval<T>(static_cast<T>(lhs) + rhs.GetLow(), static_cast<T>(lhs) + rhs.GetHigh());
00241 }
00242
00243 template<typename T>
00244 Interval<T> operator+(const Interval<T>& lhs, const float& rhs)
00245 {
00246 if( lhs.IsEmpty() )
00247 {
00248 return Interval<T>();
00249 }
00250 return Interval<T>(lhs.GetLow() + static_cast<T>(rhs), lhs.GetHigh() + static_cast<T>(rhs));
00251 }
00252
00253 template<typename T>
00254 Interval<T> operator+(const float& lhs, const Interval<T>& rhs)
00255 {
00256 if( rhs.IsEmpty() )
00257 {
00258 return Interval<T>();
00259 }
00260 return Interval<T>(static_cast<T>(lhs) + rhs.GetLow(), static_cast<T>(lhs) + rhs.GetHigh());
00261 }
00262
00263 template<typename T>
00264 Interval<T> operator-(const Interval<T>& lhs, const Interval<T>& rhs)
00265 {
00266 if( lhs.IsEmpty() || rhs.IsEmpty() )
00267 {
00268 return Interval<T>();
00269 }
00270 return Interval<T>(lhs.GetLow() - rhs.GetHigh(), lhs.GetHigh() - rhs.GetLow());
00271 }
00272
00273 template<typename T>
00274 Interval<T> operator-(const Interval<T>& lhs, const float& rhs)
00275 {
00276 if( lhs.IsEmpty() )
00277 {
00278 return Interval<T>();
00279 }
00280 return Interval<T>(lhs.GetLow() - rhs, lhs.GetHigh()-rhs);
00281 }
00282
00283 template<typename T>
00284 Interval<T> operator-(const Interval<T>& lhs, const double& rhs)
00285 {
00286 if( lhs.IsEmpty() )
00287 {
00288 return Interval<T>();
00289 }
00290 return Interval<T>(lhs.GetLow() - rhs, lhs.GetHigh()-rhs);
00291 }
00292
00293 template<typename T>
00294 Interval<T> operator-(const float& lhs, const Interval<T>& rhs)
00295 {
00296 if( rhs.IsEmpty() )
00297 {
00298 return Interval<T>();
00299 }
00300 return Interval<T>(lhs - rhs.GetHigh(), lhs-rhs.GetLow());
00301 }
00302
00303 template<typename T>
00304 Interval<T> operator-(const double& lhs, const Interval<T>& rhs)
00305 {
00306 if( rhs.IsEmpty() )
00307 {
00308 return Interval<T>();
00309 }
00310 return Interval<T>(lhs - rhs.GetHigh(), lhs-rhs.GetLow());
00311 }
00312
00313 template<typename T>
00314 Interval<T> operator-(const Interval<T>& rhs)
00315 {
00316 if( rhs.IsEmpty() )
00317 {
00318 return Interval<T>();
00319 }
00320 Interval<T> result(-rhs.GetHigh(), -rhs.GetLow());
00321 return result;
00322 }
00323
00324 template<typename T>
00325 Interval<T> operator*(const Interval<T>& lhs, const Interval<T>& rhs)
00326 {
00327 if( lhs.IsEmpty() || rhs.IsEmpty() )
00328 {
00329 return Interval<T>();
00330 }
00331
00332 T t1 = lhs.GetLow() * rhs.GetLow();
00333 T t2 = lhs.GetLow() * rhs.GetHigh();
00334 T t3 = lhs.GetHigh() * rhs.GetLow();
00335 T t4 = lhs.GetHigh() * rhs.GetHigh();
00336
00337 T low = fminf(t1, fminf(t2, fminf(t3, t4)));
00338 T high = fmaxf(t1, fmaxf(t2, fmaxf(t3, t4)));
00339
00340 return Interval<T>(low, high);
00341 }
00342
00343 template<typename T>
00344 Interval<T> operator*(const Interval<T>& lhs, const double& rhs)
00345 {
00346 Interval<T> temp(rhs, rhs);
00347 return lhs*temp;
00348 }
00349
00350 template<typename T>
00351 Interval<T> operator*(const double& lhs, const Interval<T>& rhs)
00352 {
00353 Interval<T> temp(static_cast<T>(lhs), static_cast<T>(lhs));
00354 return temp*rhs;
00355 }
00356
00357 template<typename T>
00358 Interval<T> operator*(const Interval<T>& lhs, const float& rhs)
00359 {
00360 Interval<T> temp(rhs, rhs);
00361 return lhs*temp;
00362 }
00363
00364 template<typename T>
00365 Interval<T> operator*(const float& lhs, const Interval<T>& rhs)
00366 {
00367 Interval<T> temp(lhs, lhs);
00368 return temp*rhs;
00369 }
00370
00371 template<typename T>
00372 bool Overlaps(const Interval<T>& lhs, const Interval<T>& rhs)
00373 {
00374 if( lhs.IsEmpty() || rhs.IsEmpty() )
00375 {
00376 return false;
00377 }
00378
00379 return rhs.GetHigh() >= lhs.GetLow() &&
00380 rhs.GetLow() <= lhs.GetHigh();
00381 }
00382
00383 template<typename T>
00384 Interval<T> Intersection(const Interval<T>& lhs, const Interval<T>& rhs)
00385 {
00386 if( lhs.IsEmpty() || rhs.IsEmpty() )
00387 {
00388 return Interval<T>();
00389 }
00390
00391 return Interval<T>(fmaxf(lhs.GetLow(), rhs.GetLow()),
00392 fminf(lhs.GetHigh(), rhs.GetHigh()));
00393 }
00394
00395 template<typename T>
00396 Interval<T> Union(const Interval<T>& lhs, const Interval<T>& rhs)
00397 {
00398 if( lhs.IsEmpty() || rhs.IsEmpty() )
00399 {
00400 return Interval<T>();
00401 }
00402
00403 Interval<T> result = lhs;
00404 result.Union(rhs);
00405 return result;
00406 }
00407
00408
00409 using ::exp;
00410
00411 template<typename T>
00412 Interval<T> exp(const Interval<T>& rhs)
00413 {
00414 if( rhs.IsEmpty() )
00415 {
00416 return Interval<T>();
00417 }
00418 Interval<T> result(exp(rhs.GetLow()), exp(rhs.GetHigh()));
00419 return result;
00420 }
00421
00422 template<typename T>
00423 std::ostream& operator<<(std::ostream& os, const Interval<T>& interval)
00424 {
00425 os << "[" << interval.GetLow() << ", " << interval.GetHigh() << "]";
00426 return os;
00427 }
00428
00429 }
00430 }
00431 #endif
00432