Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShIntervalImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
00027 #ifndef SHINTERVALIMPL_HPP
00028 #define SHINTERVALIMPL_HPP
00029 
00030 #include <cmath>
00031 #include "ShMath.hpp"
00032 #include "ShInterval.hpp"
00033 
00034 namespace SH {
00035 
00036 // @todo replace uses of std::fabs 
00037 
00039 template<typename T>
00040 ShInterval<T>::ShInterval()
00041 {}
00042 
00044 template<typename T>
00045 ShInterval<T>::ShInterval(const T& value)
00046   : m_lo(value), m_hi(value)
00047 {}
00048 
00050 template<typename T>
00051 ShInterval<T>::ShInterval(const T& lo, const T& hi)
00052   : m_lo(lo), m_hi(hi)
00053 {}
00054 
00055 template<typename T>
00056 template<typename T2>
00057 ShInterval<T>::ShInterval(const ShInterval<T2> &other)
00058   : m_lo((T)(other.lo())), m_hi((T)(other.hi()))
00059 {}
00060 
00062 template<typename T>
00063 T& ShInterval<T>::lo()
00064 {
00065   return m_lo;
00066 }
00067 
00068 template<typename T>
00069 const T& ShInterval<T>::lo() const
00070 {
00071   return m_lo;
00072 }
00073 
00074 template<typename T>
00075 T& ShInterval<T>::hi()
00076 {
00077   return m_hi;
00078 }
00079 
00080 template<typename T>
00081 const T& ShInterval<T>::hi() const
00082 {
00083   return m_hi;
00084 }
00085 
00087 template<typename T>
00088 const T& ShInterval<T>::width() const
00089 {
00090   return m_hi - m_lo;
00091 }
00092 
00093 template<typename T>
00094 const T& ShInterval<T>::centre() const
00095 {
00096   return (m_hi + m_lo) / 2; 
00097 }
00098 
00099 template<typename T>
00100 const T& ShInterval<T>::radius() const
00101 {
00102   return width() / 2;
00103 }
00104 
00106 template<typename T>
00107 ShInterval<T>& ShInterval<T>::operator=(const T &value)
00108 {
00109   m_lo = m_hi = value;
00110   return *this;
00111 }
00112 
00113 template<typename T>
00114 ShInterval<T>& ShInterval<T>::operator=(const ShInterval<T> &other)
00115 {
00116   m_lo = other.m_lo;
00117   m_hi = other.m_hi;
00118   return *this;
00119 }
00120 
00121 template<typename T>
00122 ShInterval<T>& ShInterval<T>::operator+=(const T &value)
00123 {
00124   m_lo += value;
00125   m_hi += value;
00126 }
00127 
00128 template<typename T>
00129 ShInterval<T>& ShInterval<T>::operator+=(const ShInterval<T> &other)
00130 {
00131   m_lo += other.m_lo;
00132   m_hi += other.m_hi;
00133   return *this;
00134 }
00135 
00136 template<typename T>
00137 ShInterval<T>& ShInterval<T>::operator-=(const T &value)
00138 {
00139   m_lo -= value;
00140   m_hi -= value;
00141 }
00142 
00143 template<typename T>
00144 ShInterval<T>& ShInterval<T>::operator-=(const ShInterval<T> &other)
00145 {
00146   m_lo -= other.m_hi;
00147   m_hi -= other.m_lo;
00148   return *this;
00149 }
00150 
00151 template<typename T>
00152 ShInterval<T>& ShInterval<T>::operator*=(const T &value)
00153 {
00154   m_lo = m_lo * value;
00155   m_hi = m_hi * value;
00156   if(value < 0) std::swap(m_lo, m_hi); 
00157   return *this;
00158 }
00159 
00160 template<typename T>
00161 ShInterval<T>& ShInterval<T>::operator*=(const ShInterval<T> &other)
00162 {
00163   T ll, lh, hl, hh;
00164   ll = m_lo * other.m_lo;
00165   lh = m_lo * other.m_hi;
00166   hl = m_hi * other.m_lo;
00167   hh = m_hi * other.m_hi;
00168 
00169   m_lo = std::min(std::min(ll, lh), std::min(hl, hh));
00170   m_hi = std::max(std::max(ll, lh), std::max(hl, hh));
00171 
00172   return *this;
00173 }
00174 
00175 template<typename T>
00176 ShInterval<T>& ShInterval<T>::operator/=(const T &value)
00177 {
00178   return (*this) *= (1 / value);
00179 }
00180 
00181 template<typename T>
00182 ShInterval<T>& ShInterval<T>::operator/=(const ShInterval<T> &other)
00183 {
00184   return (*this) *= rcp(other);
00185 }
00186 
00187 template<typename T>
00188 ShInterval<T>& ShInterval<T>::operator%=(const T &value)
00189 {
00190   // @todo
00191   m_hi = std::fabs(value);
00192   m_lo = -m_hi;
00193 }
00194 
00195 template<typename T>
00196 ShInterval<T>& ShInterval<T>::operator%=(const ShInterval<T> &other)
00197 {
00198   // @todo
00199   m_hi = std::max(std::fabs(other.lo), std::fabs(other.hi));
00200   m_lo = -m_hi;
00201 }
00202 
00204 template<typename T>
00205 ShInterval<T> ShInterval<T>::operator-() const 
00206 {
00207   return ShInterval<T>(-m_hi, -m_lo);
00208 }
00209 
00210 template<typename TT>
00211 std::ostream& operator<<(std::ostream &out, const ShInterval<TT> &value)
00212 {
00213   out << "[" << value.m_lo << "," << value.m_hi << "]";
00214   return out;
00215 }
00216 
00217 template<typename TT>
00218 std::istream& operator>>(std::istream &in, ShInterval<TT> &value)
00219 {
00220   // @todo this isn't exactly bullet-proof right now...
00221   in.ignore(1, '[');
00222   in >> value.m_lo;
00223   in.ignore(1, ',');
00224   in >> value.m_hi;
00225   in.ignore(1, ']');
00226   return in;
00227 }
00228 
00230 template<typename T>
00231 ShInterval<T> operator+(const ShInterval<T> &a, const ShInterval<T> &b) 
00232 {
00233   return ShInterval<T>(a.m_lo + b.m_lo, a.m_hi + b.m_hi);
00234 }
00235 
00236 
00237 template<typename T>
00238 ShInterval<T> operator-(const ShInterval<T> &a, const ShInterval<T> &b) 
00239 {
00240   return ShInterval<T>(a.m_lo - b.m_hi, a.m_hi - b.m_lo);
00241 }
00242 
00243 template<typename T>
00244 ShInterval<T> operator-(const T &a, const ShInterval<T> &b) 
00245 {
00246   return ShInterval<T>(a - b.m_hi, a - b.m_lo);
00247 }
00248 
00249 
00250 template<typename T>
00251 ShInterval<T> operator*(const ShInterval<T> &a, const ShInterval<T> &b) 
00252 {
00253   T ll, lh, hl, hh;
00254   ll = a.m_lo * b.m_lo;
00255   lh = a.m_lo * b.m_hi;
00256   hl = a.m_hi * b.m_lo;
00257   hh = a.m_hi * b.m_hi;
00258 
00259   return ShInterval<T>(std::min(std::min(ll, lh), std::min(hl, hh)),
00260       std::max(std::max(ll, lh), std::max(hl, hh)));
00261 }
00262 
00263 
00264 template<typename T>
00265 ShInterval<T> operator/(const ShInterval<T> &a, const ShInterval<T> &b) 
00266 {
00267   return a * rcp(b);
00268 }
00269 
00270 
00271 template<typename T>
00272 ShInterval<T> operator%(const ShInterval<T> &a, const ShInterval<T> &b) 
00273 {
00274   T large = std::max(std::fabs(b.m_lo), std::fabs(b.m_hi));
00275   return ShInterval<T>(-large, large); 
00276 }
00277 
00278 template<typename T>
00279 ShInterval<T> cbrt(const ShInterval<T> &a) 
00280 {
00281   // monotonic
00282   // @todo type check this one 
00283   return pow(a, ShInterval<T>(1.0f / 3.0f)); 
00284 }
00285 
00286 
00287 template<typename T>
00288 ShInterval<T> exp(const ShInterval<T> &a) 
00289 {
00290   // monotonic function
00291   return ShInterval<T>(std::exp(a.m_lo), std::exp(a.m_hi));
00292 }
00293 
00294 
00295 template<typename T>
00296 ShInterval<T> exp2(const ShInterval<T> &a) 
00297 {
00298   // monotonic function
00299   return ShInterval<T>(exp2f(a.m_lo), exp2f(a.m_hi));
00300 }
00301 
00302 
00303 template<typename T>
00304 ShInterval<T> exp10(const ShInterval<T> &a) 
00305 {
00306   // monotonic function
00307 return ShInterval<T>(exp10f(a.m_lo), exp10f(a.m_hi)); 
00308 }
00309 
00310 
00311 template<typename T>
00312 ShInterval<T> log(const ShInterval<T> &a) 
00313 {
00314   // monotonic, except <= 0 gives NaN 
00315   // @todo handle <= 0 with exception?
00316   return ShInterval<T>(std::log(a.m_lo), std::log(a.m_hi));
00317 }
00318 
00319 
00320 template<typename T>
00321 ShInterval<T> log2(const ShInterval<T> &a) 
00322 {
00323   // monotonic, except <= 0 gives NaN 
00324   // @todo handle <= 0 with exception or clamp?
00325   return ShInterval<T>(log2f(a.m_lo), log2f(a.m_hi));
00326 }
00327 
00328 
00329 template<typename T>
00330 ShInterval<T> log10(const ShInterval<T> &a) 
00331 {
00332   // monotonic, except <= 0 gives NaN 
00333   // @todo handle <= 0 with exception or clamp?
00334   return ShInterval<T>(log10f(a.m_lo), log10f(a.m_hi));
00335 }
00336 
00337 template<typename T>
00338 ShInterval<T> frac(const ShInterval<T> &a)
00339 {
00340   // @todo - if width > 1, then return below,
00341   // otherwise do some more figuring
00342   return ShInterval<T>(0, 1);
00343 }
00344 
00345 template<typename T>
00346 ShInterval<T> fmod(const ShInterval<T> &a, const ShInterval<T> &b) 
00347 {
00348   return a % b;
00349 }
00350 
00351 
00352 template<typename T>
00353 ShInterval<T> pow(const ShInterval<T> &a, const ShInterval<T> &b) 
00354 {
00355   // @todo check if this is optimal
00356   // @todo do integer special cases? - see NuS.cc
00357   return exp(log(a)*b);
00358 }
00359 
00360 
00361 template<typename T>
00362 ShInterval<T> rcp(const ShInterval<T> &a) 
00363 {
00364   if(a.m_lo <= 0 && a.m_hi >= 0) {
00365     // @todo handle infinities
00366     // This results in a -inf, inf interval
00367   }
00368   return ShInterval<T>(1.0 / a.m_hi, 1.0 / a.m_lo);
00369 }
00370 
00371 template<typename T>
00372 ShInterval<T> rsq(const ShInterval<T> &a) 
00373 {
00374   // @todo something better?
00375   return rcp(sqrt(a)); 
00376 }
00377 
00378 template<typename T>
00379 ShInterval<T> sgn(const ShInterval<T> &a) 
00380 {
00381   // @todo have constants for positve, negative, zero values
00382 
00383   // the usual sgn function is monotonic:
00384   return ShInterval<T>(a.m_lo < 0 ? -1 : a.m_lo > 0 ? 1 : 0,
00385                        a.m_hi < 0 ? -1 : a.m_hi > 0 ? 1 : 0);
00386 }
00387 
00388 template<typename T>
00389 ShInterval<T> sqrt(const ShInterval<T> &a) 
00390 {
00391   // monotonic, except <= 0 gives NaN
00392   // @todo handle <= 0 with exception or clamp
00393   return ShInterval<T>(std::sqrt(a.m_lo), std::sqrt(a.m_hi));
00394 }
00395 
00396 
00398 template<typename T>
00399 ShInterval<T> acos(const ShInterval<T> &a) 
00400 {
00401   // @todo
00402   return ShInterval<T>(0, M_PI);
00403 }
00404 
00405 
00406 template<typename T>
00407 ShInterval<T> asin(const ShInterval<T> &a) 
00408 {
00409   // @todo
00410   return ShInterval<T>(-M_PI/2, M_PI/2);
00411 }
00412 
00413 
00414 template<typename T>
00415 ShInterval<T> atan(const ShInterval<T> &a) 
00416 {
00417   // @todo
00418   return ShInterval<T>(-M_PI/2, M_PI/2);
00419 }
00420 
00421 
00422 template<typename T>
00423 ShInterval<T> atan2(const ShInterval<T> &a, const ShInterval<T> &b) 
00424 {
00425   // @todo
00426   return ShInterval<T>(-M_PI, M_PI);
00427 }
00428 
00429 
00430 template<typename T>
00431 ShInterval<T> cos(const ShInterval<T> &a) 
00432 {
00433   //@todo
00434   return ShInterval<T>(-1, 1);
00435 }
00436 
00437 template<typename T>
00438 ShInterval<T> sin(const ShInterval<T> &a) 
00439 {
00440   // @todo
00441   return ShInterval<T>(-1, 1);
00442 }
00443 
00444 
00445 template<typename T>
00446 ShInterval<T> tan(const ShInterval<T> &a) 
00447 {
00448   // @todo
00449   return ShInterval<T>(-1, 1); // @todo this is totally wrong...
00450 }
00451 
00452 
00454 template<typename T>
00455 ShInterval<T> __boolean_op(bool trueCond, bool falseCond) {
00456   // @todo fix this assumption that false < true
00457   // @todo special value for maybe? 
00458   // @todo make this return something special (other than Interval<T>)?
00459   
00460   if(trueCond) return ShInterval<T>(1);
00461   if(falseCond) return ShInterval<T>(0);
00462   return ShInterval<T>(0, 1);
00463 }
00464 
00465 template<typename T>
00466 ShInterval<T> operator<(const ShInterval<T> &a, const ShInterval<T> &b) 
00467 {
00468   return __boolean_op<T>(a.m_hi < b.m_lo, a.m_lo > b.m_hi);
00469 }
00470 
00471 template<typename T>
00472 ShInterval<T> operator<=(const ShInterval<T> &a, const ShInterval<T> &b) 
00473 {
00474   return __boolean_op<T>(a.m_hi <= b.m_lo, a.m_lo > b.m_hi);
00475 }
00476 
00477 template<typename T>
00478 ShInterval<T> operator>(const ShInterval<T> &a, const ShInterval<T> &b) 
00479 {
00480   return __boolean_op<T>(a.m_hi > b.m_lo, a.m_lo < b.m_hi);
00481 }
00482 
00483 template<typename T>
00484 ShInterval<T> operator>(const ShInterval<T> &a, const T &b) 
00485 {
00486   return __boolean_op<T>(a.m_hi > b, a.m_lo < b);
00487 }
00488 
00489 template<typename T>
00490 ShInterval<T> operator>=(const ShInterval<T> &a, const ShInterval<T> &b) 
00491 {
00492   return __boolean_op<T>(a.m_hi > b.m_lo, a.m_lo < b.m_hi);
00493 }
00494 
00495 template<typename T>
00496 ShInterval<T> operator==(const ShInterval<T> &a, const ShInterval<T> &b) 
00497 {
00498   return __boolean_op<T>(
00499       a.m_hi == b.m_hi && a.m_lo == b.m_lo && a.m_lo == a.m_hi,
00500       a.m_hi < b.m_lo || a.m_lo > b.m_hi);
00501 }
00502 
00503 template<typename T>
00504 ShInterval<T> operator!=(const ShInterval<T> &a, const ShInterval<T> &b) 
00505 {
00506   // @todo should use not(a==b) once we have not
00507   return __boolean_op<T>(
00508       a.m_hi < b.m_lo || a.m_lo > b.m_hi,
00509       a.m_hi == b.m_hi && a.m_lo == b.m_lo && a.m_lo == a.m_hi);
00510 }
00511 
00512 template<typename T>
00513 bool boundsEqual(const ShInterval<T> &a, const ShInterval<T> &b) 
00514 {
00515   return (a.lo() == b.lo()) && (a.hi() == b.hi());
00516 }
00517 
00518 
00519 
00521 template<typename T>
00522 ShInterval<T> min(const ShInterval<T> &a, const ShInterval<T> &b) 
00523 {
00524   return ShInterval<T>(std::min(a.m_lo, b.m_lo), std::min(a.m_hi, b.m_hi));
00525 }
00526 
00527 template<typename T>
00528 ShInterval<T> max(const ShInterval<T> &a, const ShInterval<T> &b) 
00529 {
00530   return ShInterval<T>(std::max(a.m_lo, b.m_lo), std::max(a.m_hi, b.m_hi));
00531 }
00532 
00533 template<typename T>
00534 ShInterval<T> floor(const ShInterval<T> &a) 
00535 {
00536   // monotonic
00537   return ShInterval<T>(std::floor(a.m_lo), std::floor(a.m_hi));
00538 }
00539 
00540 template<typename T>
00541 ShInterval<T> ceil(const ShInterval<T> &a) 
00542 {
00543   // monotonic
00544   return ShInterval<T>(std::ceil(a.m_lo), std::ceil(a.m_hi));
00545 }
00546 
00547 template<typename T>
00548 ShInterval<T> rnd(const ShInterval<T> &a) 
00549 {
00550   // monotonic
00551   // @todo type handle this in general
00552   return ShInterval<T>(std::floor(a.m_lo + 0.5f), std::floor(a.m_hi + 0.5f));
00553 }
00554 
00555 template<typename T>
00556 ShInterval<T> abs(const ShInterval<T> &a) 
00557 {
00558   T lo, hi;
00559 
00560   hi = std::max(std::fabs(a.m_lo), std::fabs(a.m_hi));
00561   lo = std::min(std::fabs(a.m_lo), std::fabs(a.m_hi));
00562   if(a.m_lo <= 0 && a.m_hi >= 0) lo = 0;
00563   return ShInterval<T>(lo, hi);
00564 }
00565 
00567 template<typename T>
00568 ShInterval<T> cond(const ShInterval<T> &a, const ShInterval<T> &b, 
00569     const ShInterval<T> &c)
00570 {
00571   return lerp(a > (T)(0), b, c);
00572 }
00573 
00574 template<typename T>
00575 ShInterval<T> lerp(const ShInterval<T> &a, const ShInterval<T> &b, const ShInterval<T> &c) 
00576 {
00577   return a * b + ((T)(1) - a) * c;
00578 }
00579 
00580 }
00581 
00582 #endif

Generated on Mon Jan 24 18:36:32 2005 for Sh by  doxygen 1.4.1