ShFractionImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2006 Serious Hack Inc.
00004 // 
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00018 // MA  02110-1301, USA
00020 #ifndef SHFRACTIONALIMPL_HPP
00021 #define SHFRACTIONALIMPL_HPP
00022 
00023 #include <cmath>
00024 #include "ShMath.hpp"
00025 #include "ShFraction.hpp"
00026 
00027 namespace SH {
00028 
00029 #define _CompType typename ShFraction<T>::CompType 
00030 #define _LongType typename ShFraction<T>::LongType 
00031 #define _SignedLongType typename ShFraction<T>::SignedLongType 
00032 
00033 // @todo replace uses of std::fabs 
00034 
00035 template<typename T/* @todo clamp , bool Clamp */>
00036 ShFraction<T>::ShFraction()
00037 {}
00038 
00039 template<typename T/* @todo clamp , bool Clamp */>
00040 ShFraction<T>::ShFraction(double value)
00041   : m_val(clamp_val(value))
00042 {
00043 }
00044 
00045 template<typename T/* @todo clamp , bool Clamp */>
00046 ShFraction<T> ShFraction<T>::make_fraction(CompType value)
00047 {
00048   ShFraction result;
00049   result.m_val = clamp_val(value);
00050   return result; 
00051 }
00052 
00053 template<typename T/* @todo clamp , bool Clamp */>
00054 ShFraction<T> ShFraction<T>::make_fraction_signed(SignedLongType value)
00055 {
00056   ShFraction result;
00057   result.m_val = clamp_val_signed(value);
00058   return result; 
00059 }
00060 
00061 template<typename T/* @todo clamp , bool Clamp */>
00062 template<typename T2>
00063 ShFraction<T>::ShFraction(const ShFraction<T2> &other)
00064   : m_val(clamp_val(other.get_double())) 
00065 {
00066 }
00067 
00069 template<typename T/* @todo clamp , bool Clamp */>
00070 ShFraction<T>::operator double() const
00071 {
00072   return get_double(); 
00073 }
00074 
00075 template<typename T/* @todo clamp , bool Clamp */>
00076 T& ShFraction<T>::val()
00077 {
00078   return m_val;
00079 }
00080 
00081 template<typename T/* @todo clamp , bool Clamp */>
00082 T ShFraction<T>::val() const
00083 {
00084   return m_val;
00085 }
00086 
00088 template<typename T/* @todo clamp , bool Clamp */>
00089 ShFraction<T>& ShFraction<T>::operator=(double value)
00090 {
00091   m_val = clamp_val(value);
00092   return *this;
00093 }
00094 
00095 template<typename T/* @todo clamp , bool Clamp */>
00096 ShFraction<T>& ShFraction<T>::operator=(const ShFraction& other)
00097 {
00098   m_val = other.m_val;
00099   return *this;
00100 }
00101 
00102 template<typename T/* @todo clamp , bool Clamp */>
00103 ShFraction<T>& ShFraction<T>::operator+=(double value)
00104 {
00105   return operator+=(ShFraction(value));
00106 }
00107 
00108 template<typename T/* @todo clamp , bool Clamp */>
00109 ShFraction<T>& ShFraction<T>::operator+=(const ShFraction& other)
00110 {
00111   m_val = clamp_val(CompType(m_val) + CompType(other.m_val));
00112   return *this;
00113 }
00114 
00115 template<typename T/* @todo clamp , bool Clamp */>
00116 ShFraction<T>& ShFraction<T>::operator-=(double value)
00117 {
00118   return operator-=(ShFraction(value));
00119 }
00120 
00121 template<typename T/* @todo clamp , bool Clamp */>
00122 ShFraction<T>& ShFraction<T>::operator-=(const ShFraction& other)
00123 {
00124   m_val = clamp_val_signed(SignedLongType(m_val) - SignedLongType(other.m_val));
00125   return *this;
00126 }
00127 
00128 template<typename T/* @todo clamp , bool Clamp */>
00129 ShFraction<T>& ShFraction<T>::operator*=(double value)
00130 {
00131   return operator*=(ShFraction(value)); 
00132 }
00133 
00134 template<typename T/* @todo clamp , bool Clamp */>
00135 ShFraction<T>& ShFraction<T>::operator*=(const ShFraction& other)
00136 {
00137   m_val = clamp_val(CompType(m_val) * CompType(other.m_val));
00138   return *this;
00139 }
00140 
00141 template<typename T/* @todo clamp , bool Clamp */>
00142 ShFraction<T>& ShFraction<T>::operator/=(double value)
00143 {
00144   return operator/=(ShFraction(value)); 
00145 }
00146 
00147 template<typename T/* @todo clamp , bool Clamp */>
00148 ShFraction<T>& ShFraction<T>::operator/=(const ShFraction& other)
00149 {
00150   LongType numerator = LongType(m_val) << BITS;   
00151   LongType denom = LongType(other.m_val);
00152   m_val = clamp_val(numerator / denom);
00153   return (*this); 
00154 }
00155 
00156 template<typename T/* @todo clamp , bool Clamp */>
00157 ShFraction<T>& ShFraction<T>::operator%=(double value)
00158 {
00159   return operator%=(ShFraction(value));
00160 }
00161 
00162 template<typename T/* @todo clamp , bool Clamp */>
00163 ShFraction<T>& ShFraction<T>::operator%=(const ShFraction& other)
00164 {
00165   // @todo range - should need no clamping for this
00166   m_val = m_val % other.m_val;
00167   if(m_val < 0) m_val += other.m_val;
00168 }
00169 
00171 template<typename T/* @todo clamp , bool Clamp */>
00172 ShFraction<T> ShFraction<T>::operator-() const 
00173 {
00174   if(is_signed /* @todo clamp && Clamp */) return make_fraction(0); 
00175   return make_fraction(-m_val);
00176 }
00177 
00178 template<typename TT>
00179 std::ostream& operator<<(std::ostream &out, const ShFraction<TT> &value)
00180 {
00181   out << double(value);
00182   return out;
00183 }
00184 
00185 template<typename TT>
00186 std::istream& operator>>(std::istream &in, ShFraction<TT> &value)
00187 {
00188   double temp;
00189   in >> temp;
00190   value = temp;
00191   return in;
00192 }
00193 
00194 template<typename T/* @todo clamp , bool Clamp */>
00195 inline
00196 double ShFraction<T>::get_double() const
00197 {
00198   return double(m_val) / double(ONE);
00199 }
00200 
00201 template<typename T/* @todo clamp , bool Clamp */>
00202 inline
00203 T ShFraction<T>::clamp_val(double value)
00204 {
00205   double temp = value * ONE;
00206 
00207 /* @todo clamp  if(Clamp) { */
00208     temp = std::max(std::min(temp, double(MAX)), double(MIN));
00209 /* @todo clamp  } */
00210   return T(temp);
00211 }
00212 
00213 template<typename T/* @todo clamp , bool Clamp */>
00214 inline
00215 T ShFraction<T>::clamp_val(CompType value)
00216 {
00217   /* @todo clamp if(Clamp) { */
00218     value = std::max(std::min(value, CompType(MAX)), CompType(MIN));
00219   /* @todo clamp } */
00220   return T(value);
00221 }
00222 
00223 template<typename T/* @todo clamp , bool Clamp */>
00224 inline
00225 T ShFraction<T>::clamp_val_signed(SignedLongType value)
00226 {
00227   /* @todo clamp if(Clamp) { */
00228     value = std::max(std::min(value, SignedLongType(MAX)), SignedLongType(MIN));
00229   /* @todo clamp } */
00230   return T(value);
00231 }
00232 
00234 template<typename T/* @todo clamp , bool Clamp */>
00235 ShFraction<T> operator+(const ShFraction<T> &a, const ShFraction<T> &b) 
00236 {
00237   return ShFraction<T>::make_fraction(_CompType(a.m_val) + _CompType(b.m_val));
00238 }
00239 
00240 
00241 template<typename T/* @todo clamp , bool Clamp */>
00242 ShFraction<T> operator-(const ShFraction<T> &a, const ShFraction<T> &b) 
00243 {
00244   return ShFraction<T>::make_fraction_signed(
00245       _SignedLongType(a.m_val) - 
00246       _SignedLongType(b.m_val));
00247 }
00248 
00249 template<typename T/* @todo clamp , bool Clamp */>
00250 ShFraction<T> operator*(const ShFraction<T> &a, const ShFraction<T> &b) 
00251 {
00252   return ShFraction<T>::make_fraction(_CompType(a.m_val) * _CompType(b.m_val));
00253 }
00254 
00255 
00256 template<typename T/* @todo clamp , bool Clamp */>
00257 ShFraction<T> operator/(const ShFraction<T> &a, const ShFraction<T> &b) 
00258 {
00259   _LongType numerator = _LongType(a.m_val) << ShFraction<T>::BITS;   
00260   _LongType denom = _LongType(b.m_val);
00261   return ShFraction<T>::make_fraction(numerator / denom);
00262 }
00263 
00264 
00265 template<typename T/* @todo clamp , bool Clamp */>
00266 ShFraction<T> operator%(const ShFraction<T> &a, const ShFraction<T> &b) 
00267 {
00268   T temp = a.m_val % b.m_val;
00269   if(temp < 0) temp += b.m_val; 
00270   return ShFraction<T>(temp);
00271 }
00272 
00273 template<typename T/* @todo clamp , bool Clamp */>
00274 ShFraction<T> cbrt(const ShFraction<T> &a) 
00275 {
00276   return ShFraction<T>(std::pow(double(a), 1.0 / 3.0)); 
00277 }
00278 
00279 
00280 template<typename T/* @todo clamp , bool Clamp */>
00281 ShFraction<T> exp(const ShFraction<T> &a) 
00282 {
00283   return ShFraction<T>(std::exp(double(a))); 
00284 }
00285 
00286 
00287 template<typename T/* @todo clamp , bool Clamp */>
00288 ShFraction<T> exp2(const ShFraction<T> &a) 
00289 {
00290   return ShFraction<T>(std::pow(2.0, double(a))); 
00291 }
00292 
00293 
00294 template<typename T/* @todo clamp , bool Clamp */>
00295 ShFraction<T> exp10(const ShFraction<T> &a) 
00296 {
00297   return ShFraction<T>(std::pow(10.0, double(a))); 
00298 }
00299 
00300 
00301 template<typename T/* @todo clamp , bool Clamp */>
00302 ShFraction<T> log(const ShFraction<T> &a) 
00303 {
00304   return ShFraction<T>(std::log(double(a))); 
00305 }
00306 
00307 
00308 template<typename T/* @todo clamp , bool Clamp */>
00309 ShFraction<T> log2(const ShFraction<T> &a) 
00310 {
00311   return ShFraction<T>(log2f(double(a))); 
00312 }
00313 
00314 
00315 template<typename T/* @todo clamp , bool Clamp */>
00316 ShFraction<T> log10(const ShFraction<T> &a) 
00317 {
00318   return ShFraction<T>(log10f(double(a))); 
00319 }
00320 
00321 template<typename T/* @todo clamp , bool Clamp */>
00322 ShFraction<T> frac(const ShFraction<T> &a)
00323 {
00324   T result = a.m_val;
00325   if(result < 0) {
00326     result += ShFraction<T>::ONE;
00327   }
00328   return ShFraction<T>(result);
00329 }
00330 
00331 template<typename T/* @todo clamp , bool Clamp */>
00332 ShFraction<T> fmod(const ShFraction<T> &a, const ShFraction<T> &b) 
00333 {
00334   return a % b;
00335 }
00336 
00337 
00338 template<typename T/* @todo clamp , bool Clamp */>
00339 ShFraction<T> pow(const ShFraction<T> &a, const ShFraction<T> &b) 
00340 {
00341   // @todo check if this is optimal
00342   // @todo do integer special cases? - see NuS.cc
00343   return ShFraction<T>(std::pow(double(a), double(b))); 
00344 }
00345 
00346 
00347 // not a good function for fractional types...
00348 // guaranteed to overflow...DOH
00349 template<typename T/* @todo clamp , bool Clamp */>
00350 ShFraction<T> rcp(const ShFraction<T> &a) 
00351 {
00352   if(a.m_val > 0) return ShFraction<T>(ShFraction<T>::MAX);
00353   return ShFraction<T>(ShFraction<T>::MIN);
00354 }
00355 
00356 template<typename T/* @todo clamp , bool Clamp */>
00357 ShFraction<T> rsq(const ShFraction<T> &a) 
00358 {
00359   return rcp(a); // same bad behaviour 
00360 }
00361 
00362 template<typename T/* @todo clamp , bool Clamp */>
00363 ShFraction<T> sgn(const ShFraction<T> &a) 
00364 {
00365   return ShFraction<T>(a.m_val > 0 ? 1 : a.m_val == 0 ? 0 : -1); 
00366 }
00367 
00368 template<typename T/* @todo clamp , bool Clamp */>
00369 ShFraction<T> sqrt(const ShFraction<T> &a) 
00370 {
00371   return ShFraction<T>(std::sqrt(double(a)));
00372 }
00373 
00374 
00376 template<typename T/* @todo clamp , bool Clamp */>
00377 ShFraction<T> acos(const ShFraction<T> &a) 
00378 {
00379   return ShFraction<T>(std::acos(double(a)));
00380 }
00381 
00382 
00383 template<typename T/* @todo clamp , bool Clamp */>
00384 ShFraction<T> asin(const ShFraction<T> &a) 
00385 {
00386   return ShFraction<T>(std::asin(double(a)));
00387 }
00388 
00389 
00390 template<typename T/* @todo clamp , bool Clamp */>
00391 ShFraction<T> atan(const ShFraction<T> &a) 
00392 {
00393   return ShFraction<T>(std::atan(double(a)));
00394 }
00395 
00396 
00397 template<typename T/* @todo clamp , bool Clamp */>
00398 ShFraction<T> atan2(const ShFraction<T> &a, const ShFraction<T> &b) 
00399 {
00400   return ShFraction<T>(std::atan2(double(a), double(b)));
00401 }
00402 
00403 
00404 template<typename T/* @todo clamp , bool Clamp */>
00405 ShFraction<T> cos(const ShFraction<T> &a) 
00406 {
00407   return ShFraction<T>(std::cos(double(a)));
00408 }
00409 
00410 template<typename T/* @todo clamp , bool Clamp */>
00411 ShFraction<T> sin(const ShFraction<T> &a) 
00412 {
00413   return ShFraction<T>(std::sin(double(a)));
00414 }
00415 
00416 
00417 template<typename T/* @todo clamp , bool Clamp */>
00418 ShFraction<T> tan(const ShFraction<T> &a) 
00419 {
00420   return ShFraction<T>(std::tan(double(a)));
00421 }
00422 
00423 
00425 template<typename T/* @todo clamp , bool Clamp */>
00426 bool operator<(const ShFraction<T> &a, const ShFraction<T> &b) 
00427 {
00428   return (a.m_val < b.m_val);
00429 }
00430 
00431 template<typename T/* @todo clamp , bool Clamp */>
00432 bool operator<=(const ShFraction<T> &a, const ShFraction<T> &b) 
00433 {
00434   return (a.m_val <= b.m_val);
00435 }
00436 
00437 template<typename T/* @todo clamp , bool Clamp */>
00438 bool operator>(const ShFraction<T> &a, const ShFraction<T> &b) 
00439 {
00440   return (a.m_val > b.m_val);
00441 }
00442 
00443 template<typename T/* @todo clamp , bool Clamp */>
00444 bool operator>=(const ShFraction<T> &a, const ShFraction<T> &b) 
00445 {
00446   return (a.m_val >= b.m_val);
00447 }
00448 
00449 template<typename T/* @todo clamp , bool Clamp */>
00450 bool operator==(const ShFraction<T> &a, const ShFraction<T> &b) 
00451 {
00452   return (a.m_val == b.m_val);
00453 }
00454 
00455 template<typename T/* @todo clamp , bool Clamp */>
00456 bool operator!=(const ShFraction<T> &a, const ShFraction<T> &b) 
00457 {
00458   return (a.m_val != b.m_val);
00459 }
00460 
00462 template<typename T/* @todo clamp , bool Clamp */>
00463 ShFraction<T> min(const ShFraction<T> &a, const ShFraction<T> &b) 
00464 {
00465   return ShFraction<T>(std::min(a.m_val, b.m_val));
00466 }
00467 
00468 template<typename T/* @todo clamp , bool Clamp */>
00469 ShFraction<T> max(const ShFraction<T> &a, const ShFraction<T> &b) 
00470 {
00471   return ShFraction<T>(std::max(a.m_val, b.m_val));
00472 }
00473 
00474 template<typename T/* @todo clamp , bool Clamp */>
00475 ShFraction<T> floor(const ShFraction<T> &a) 
00476 {
00477 
00478   T result = 0; 
00479   if(a.m_val == ShFraction<T>::ONE) {
00480     result = ShFraction<T>::ONE;
00481   } else if(ShFraction<T>::is_signed && a.m_val < 0) {
00482     a.m_val = -ShFraction<T>::ONE;
00483   }
00484   return ShFraction<T>(result); 
00485 }
00486 
00487 template<typename T/* @todo clamp , bool Clamp */>
00488 ShFraction<T> ceil(const ShFraction<T> &a) 
00489 {
00490   T ONE = ShFraction<T>::ONE;
00491   T result = 0; 
00492   if(a.m_val > 0) {
00493     result = ONE;
00494   } else if(ShFraction<T>::is_signed && 
00495       a.m_val == -ONE) {
00496     result = -ONE;
00497   }
00498   return ShFraction<T>(result);
00499 }
00500 
00501 template<typename T/* @todo clamp , bool Clamp */>
00502 ShFraction<T> rnd(const ShFraction<T> &a) 
00503 {
00504   T ONE = ShFraction<T>::ONE;
00505   T HALF = ONE >> 1; // slightly less than half
00506   T result;
00507   if(a.m_val > HALF) {
00508     result = ONE;
00509   } else if(!ShFraction<T>::is_signed || result > -HALF) {
00510     result = 0;
00511   } else {
00512     result = -ONE;
00513   }
00514   return ShFraction<T>(result); 
00515 }
00516 
00517 template<typename T/* @todo clamp , bool Clamp */>
00518 ShFraction<T> abs(const ShFraction<T> &a) 
00519 {
00520   return ShFraction<T>(a.m_val < 0 ? -a.m_val: a.m_val);
00521 }
00522 
00524 template<typename T/* @todo clamp , bool Clamp */>
00525 ShFraction<T> cond(const ShFraction<T> &a, const ShFraction<T> &b, 
00526     const ShFraction<T> &c)
00527 {
00528   return ShFraction<T>(a.m_val > 0 ? b.m_val: c.m_val); 
00529 }
00530 
00531 template<typename T/* @todo clamp , bool Clamp */>
00532 ShFraction<T> lerp(const ShFraction<T> &a, const ShFraction<T> &b, const ShFraction<T> &c) 
00533 {
00534   T ONE = ShFraction<T>(ShFraction<T>::ONE);
00535   return a * b + (ONE - a) * c;
00536 }
00537 
00538 #undef _CompType
00539 #undef _LongType
00540 #undef _SignedLongType
00541 }
00542 
00543 #endif

Generated on Thu Feb 16 14:51:32 2006 for Sh by  doxygen 1.4.6