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