00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
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
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
00282
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
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
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
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
00315
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
00324
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
00333
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
00341
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
00356
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
00366
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
00375 return rcp(sqrt(a));
00376 }
00377
00378 template<typename T>
00379 ShInterval<T> sgn(const ShInterval<T> &a)
00380 {
00381
00382
00383
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
00392
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
00402 return ShInterval<T>(0, M_PI);
00403 }
00404
00405
00406 template<typename T>
00407 ShInterval<T> asin(const ShInterval<T> &a)
00408 {
00409
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
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
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
00434 return ShInterval<T>(-1, 1);
00435 }
00436
00437 template<typename T>
00438 ShInterval<T> sin(const ShInterval<T> &a)
00439 {
00440
00441 return ShInterval<T>(-1, 1);
00442 }
00443
00444
00445 template<typename T>
00446 ShInterval<T> tan(const ShInterval<T> &a)
00447 {
00448
00449 return ShInterval<T>(-1, 1);
00450 }
00451
00452
00454 template<typename T>
00455 ShInterval<T> __boolean_op(bool trueCond, bool falseCond) {
00456
00457
00458
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
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
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
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
00551
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