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 SHFRACTIONALIMPL_HPP
00028 #define SHFRACTIONALIMPL_HPP
00029
00030 #include <cmath>
00031 #include "ShMath.hpp"
00032 #include "ShFraction.hpp"
00033
00034 namespace SH {
00035
00036 #define _CompType typename ShFraction<T>::CompType
00037 #define _LongType typename ShFraction<T>::LongType
00038 #define _SignedLongType typename ShFraction<T>::SignedLongType
00039
00040
00041
00042 template<typename T>
00043 ShFraction<T>::ShFraction()
00044 {}
00045
00046 template<typename T>
00047 ShFraction<T>::ShFraction(double value)
00048 : m_val(clamp_val(value))
00049 {
00050 }
00051
00052 template<typename T>
00053 ShFraction<T> ShFraction<T>::make_fraction(CompType value)
00054 {
00055 ShFraction result;
00056 result.m_val = clamp_val(value);
00057 return result;
00058 }
00059
00060 template<typename T>
00061 ShFraction<T> ShFraction<T>::make_fraction_signed(SignedLongType value)
00062 {
00063 ShFraction result;
00064 result.m_val = clamp_val_signed(value);
00065 return result;
00066 }
00067
00068 template<typename T>
00069 template<typename T2>
00070 ShFraction<T>::ShFraction(const ShFraction<T2> &other)
00071 : m_val(clamp_val(other.get_double()))
00072 {
00073 }
00074
00076 template<typename T>
00077 ShFraction<T>::operator double() const
00078 {
00079 return get_double();
00080 }
00081
00082 template<typename T>
00083 T& ShFraction<T>::val()
00084 {
00085 return m_val;
00086 }
00087
00088 template<typename T>
00089 T ShFraction<T>::val() const
00090 {
00091 return m_val;
00092 }
00093
00095 template<typename T>
00096 ShFraction<T>& ShFraction<T>::operator=(double value)
00097 {
00098 m_val = clamp_val(value);
00099 return *this;
00100 }
00101
00102 template<typename T>
00103 ShFraction<T>& ShFraction<T>::operator=(const ShFraction& other)
00104 {
00105 m_val = other.m_val;
00106 return *this;
00107 }
00108
00109 template<typename T>
00110 ShFraction<T>& ShFraction<T>::operator+=(double value)
00111 {
00112 return operator+=(ShFraction(value));
00113 }
00114
00115 template<typename T>
00116 ShFraction<T>& ShFraction<T>::operator+=(const ShFraction& other)
00117 {
00118 m_val = clamp_val(CompType(m_val) + CompType(other.m_val));
00119 return *this;
00120 }
00121
00122 template<typename T>
00123 ShFraction<T>& ShFraction<T>::operator-=(double value)
00124 {
00125 return operator-=(ShFraction(value));
00126 }
00127
00128 template<typename T>
00129 ShFraction<T>& ShFraction<T>::operator-=(const ShFraction& other)
00130 {
00131 m_val = clamp_val_signed(SignedLongType(m_val) - SignedLongType(other.m_val));
00132 return *this;
00133 }
00134
00135 template<typename T>
00136 ShFraction<T>& ShFraction<T>::operator*=(double value)
00137 {
00138 return operator*=(ShFraction(value));
00139 }
00140
00141 template<typename T>
00142 ShFraction<T>& ShFraction<T>::operator*=(const ShFraction& other)
00143 {
00144 m_val = clamp_val(CompType(m_val) * CompType(other.m_val));
00145 return *this;
00146 }
00147
00148 template<typename T>
00149 ShFraction<T>& ShFraction<T>::operator/=(double value)
00150 {
00151 return operator/=(ShFraction(value));
00152 }
00153
00154 template<typename T>
00155 ShFraction<T>& ShFraction<T>::operator/=(const ShFraction& other)
00156 {
00157 LongType numerator = LongType(m_val) << BITS;
00158 LongType denom = LongType(other.m_val);
00159 m_val = clamp_val(numerator / denom);
00160 return (*this);
00161 }
00162
00163 template<typename T>
00164 ShFraction<T>& ShFraction<T>::operator%=(double value)
00165 {
00166 return operator%=(ShFraction(value));
00167 }
00168
00169 template<typename T>
00170 ShFraction<T>& ShFraction<T>::operator%=(const ShFraction& other)
00171 {
00172
00173 m_val = m_val % other.m_val;
00174 if(m_val < 0) m_val += other.m_val;
00175 }
00176
00178 template<typename T>
00179 ShFraction<T> ShFraction<T>::operator-() const
00180 {
00181 if(is_signed ) return make_fraction(0);
00182 return make_fraction(-m_val);
00183 }
00184
00185 template<typename TT>
00186 std::ostream& operator<<(std::ostream &out, const ShFraction<TT> &value)
00187 {
00188 out << double(value);
00189 return out;
00190 }
00191
00192 template<typename TT>
00193 std::istream& operator>>(std::istream &in, ShFraction<TT> &value)
00194 {
00195 double temp;
00196 in >> temp;
00197 value = temp;
00198 return in;
00199 }
00200
00201 template<typename T>
00202 inline
00203 double ShFraction<T>::get_double() const
00204 {
00205 return double(m_val) / double(ONE);
00206 }
00207
00208 template<typename T>
00209 inline
00210 T ShFraction<T>::clamp_val(double value)
00211 {
00212 double temp = value * ONE;
00213
00214
00215 temp = std::max(std::min(temp, double(MAX)), double(MIN));
00216
00217 return T(temp);
00218 }
00219
00220 template<typename T>
00221 inline
00222 T ShFraction<T>::clamp_val(CompType value)
00223 {
00224
00225 value = std::max(std::min(value, CompType(MAX)), CompType(MIN));
00226
00227 return T(value);
00228 }
00229
00230 template<typename T>
00231 inline
00232 T ShFraction<T>::clamp_val_signed(SignedLongType value)
00233 {
00234
00235 value = std::max(std::min(value, SignedLongType(MAX)), SignedLongType(MIN));
00236
00237 return T(value);
00238 }
00239
00241 template<typename T>
00242 ShFraction<T> operator+(const ShFraction<T> &a, const ShFraction<T> &b)
00243 {
00244 return ShFraction<T>::make_fraction(_CompType(a.m_val) + _CompType(b.m_val));
00245 }
00246
00247
00248 template<typename T>
00249 ShFraction<T> operator-(const ShFraction<T> &a, const ShFraction<T> &b)
00250 {
00251 return ShFraction<T>::make_fraction_signed(
00252 _SignedLongType(a.m_val) -
00253 _SignedLongType(b.m_val));
00254 }
00255
00256 template<typename T>
00257 ShFraction<T> operator*(const ShFraction<T> &a, const ShFraction<T> &b)
00258 {
00259 return ShFraction<T>::make_fraction(_CompType(a.m_val) * _CompType(b.m_val));
00260 }
00261
00262
00263 template<typename T>
00264 ShFraction<T> operator/(const ShFraction<T> &a, const ShFraction<T> &b)
00265 {
00266 _LongType numerator = _LongType(a.m_val) << ShFraction<T>::BITS;
00267 _LongType denom = _LongType(b.m_val);
00268 return ShFraction<T>::make_fraction(numerator / denom);
00269 }
00270
00271
00272 template<typename T>
00273 ShFraction<T> operator%(const ShFraction<T> &a, const ShFraction<T> &b)
00274 {
00275 T temp = a.m_val % b.m_val;
00276 if(temp < 0) temp += b.m_val;
00277 return ShFraction<T>(temp);
00278 }
00279
00280 template<typename T>
00281 ShFraction<T> cbrt(const ShFraction<T> &a)
00282 {
00283 return ShFraction<T>(std::pow(double(a), 1.0 / 3.0));
00284 }
00285
00286
00287 template<typename T>
00288 ShFraction<T> exp(const ShFraction<T> &a)
00289 {
00290 return ShFraction<T>(std::exp(double(a)));
00291 }
00292
00293
00294 template<typename T>
00295 ShFraction<T> exp2(const ShFraction<T> &a)
00296 {
00297 return ShFraction<T>(std::pow(2.0, double(a)));
00298 }
00299
00300
00301 template<typename T>
00302 ShFraction<T> exp10(const ShFraction<T> &a)
00303 {
00304 return ShFraction<T>(std::pow(10.0, double(a)));
00305 }
00306
00307
00308 template<typename T>
00309 ShFraction<T> log(const ShFraction<T> &a)
00310 {
00311 return ShFraction<T>(std::log(double(a)));
00312 }
00313
00314
00315 template<typename T>
00316 ShFraction<T> log2(const ShFraction<T> &a)
00317 {
00318 return ShFraction<T>(log2f(double(a)));
00319 }
00320
00321
00322 template<typename T>
00323 ShFraction<T> log10(const ShFraction<T> &a)
00324 {
00325 return ShFraction<T>(log10f(double(a)));
00326 }
00327
00328 template<typename T>
00329 ShFraction<T> frac(const ShFraction<T> &a)
00330 {
00331 T result = a.m_val;
00332 if(result < 0) {
00333 result += ShFraction<T>::ONE;
00334 }
00335 return ShFraction<T>(result);
00336 }
00337
00338 template<typename T>
00339 ShFraction<T> fmod(const ShFraction<T> &a, const ShFraction<T> &b)
00340 {
00341 return a % b;
00342 }
00343
00344
00345 template<typename T>
00346 ShFraction<T> pow(const ShFraction<T> &a, const ShFraction<T> &b)
00347 {
00348
00349
00350 return ShFraction<T>(std::pow(double(a), double(b)));
00351 }
00352
00353
00354
00355
00356 template<typename T>
00357 ShFraction<T> rcp(const ShFraction<T> &a)
00358 {
00359 if(a.m_val > 0) return ShFraction<T>(ShFraction<T>::MAX);
00360 return ShFraction<T>(ShFraction<T>::MIN);
00361 }
00362
00363 template<typename T>
00364 ShFraction<T> rsq(const ShFraction<T> &a)
00365 {
00366 return rcp(a);
00367 }
00368
00369 template<typename T>
00370 ShFraction<T> sgn(const ShFraction<T> &a)
00371 {
00372 return ShFraction<T>(a.m_val > 0 ? 1 : a.m_val == 0 ? 0 : -1);
00373 }
00374
00375 template<typename T>
00376 ShFraction<T> sqrt(const ShFraction<T> &a)
00377 {
00378 return ShFraction<T>(std::sqrt(double(a)));
00379 }
00380
00381
00383 template<typename T>
00384 ShFraction<T> acos(const ShFraction<T> &a)
00385 {
00386 return ShFraction<T>(std::acos(double(a)));
00387 }
00388
00389
00390 template<typename T>
00391 ShFraction<T> asin(const ShFraction<T> &a)
00392 {
00393 return ShFraction<T>(std::asin(double(a)));
00394 }
00395
00396
00397 template<typename T>
00398 ShFraction<T> atan(const ShFraction<T> &a)
00399 {
00400 return ShFraction<T>(std::atan(double(a)));
00401 }
00402
00403
00404 template<typename T>
00405 ShFraction<T> atan2(const ShFraction<T> &a, const ShFraction<T> &b)
00406 {
00407 return ShFraction<T>(std::atan2(double(a), double(b)));
00408 }
00409
00410
00411 template<typename T>
00412 ShFraction<T> cos(const ShFraction<T> &a)
00413 {
00414 return ShFraction<T>(std::cos(double(a)));
00415 }
00416
00417 template<typename T>
00418 ShFraction<T> sin(const ShFraction<T> &a)
00419 {
00420 return ShFraction<T>(std::sin(double(a)));
00421 }
00422
00423
00424 template<typename T>
00425 ShFraction<T> tan(const ShFraction<T> &a)
00426 {
00427 return ShFraction<T>(std::tan(double(a)));
00428 }
00429
00430
00432 template<typename T>
00433 bool operator<(const ShFraction<T> &a, const ShFraction<T> &b)
00434 {
00435 return (a.m_val < b.m_val);
00436 }
00437
00438 template<typename T>
00439 bool operator<=(const ShFraction<T> &a, const ShFraction<T> &b)
00440 {
00441 return (a.m_val <= b.m_val);
00442 }
00443
00444 template<typename T>
00445 bool operator>(const ShFraction<T> &a, const ShFraction<T> &b)
00446 {
00447 return (a.m_val > b.m_val);
00448 }
00449
00450 template<typename T>
00451 bool operator>=(const ShFraction<T> &a, const ShFraction<T> &b)
00452 {
00453 return (a.m_val >= b.m_val);
00454 }
00455
00456 template<typename T>
00457 bool operator==(const ShFraction<T> &a, const ShFraction<T> &b)
00458 {
00459 return (a.m_val == b.m_val);
00460 }
00461
00462 template<typename T>
00463 bool operator!=(const ShFraction<T> &a, const ShFraction<T> &b)
00464 {
00465 return (a.m_val != b.m_val);
00466 }
00467
00469 template<typename T>
00470 ShFraction<T> min(const ShFraction<T> &a, const ShFraction<T> &b)
00471 {
00472 return ShFraction<T>(std::min(a.m_val, b.m_val));
00473 }
00474
00475 template<typename T>
00476 ShFraction<T> max(const ShFraction<T> &a, const ShFraction<T> &b)
00477 {
00478 return ShFraction<T>(std::max(a.m_val, b.m_val));
00479 }
00480
00481 template<typename T>
00482 ShFraction<T> floor(const ShFraction<T> &a)
00483 {
00484
00485 T result = 0;
00486 if(a.m_val == ShFraction<T>::ONE) {
00487 result = ShFraction<T>::ONE;
00488 } else if(ShFraction<T>::is_signed && a.m_val < 0) {
00489 a.m_val = -ShFraction<T>::ONE;
00490 }
00491 return ShFraction<T>(result);
00492 }
00493
00494 template<typename T>
00495 ShFraction<T> ceil(const ShFraction<T> &a)
00496 {
00497 T ONE = ShFraction<T>::ONE;
00498 T result = 0;
00499 if(a.m_val > 0) {
00500 result = ONE;
00501 } else if(ShFraction<T>::is_signed &&
00502 a.m_val == -ONE) {
00503 result = -ONE;
00504 }
00505 return ShFraction<T>(result);
00506 }
00507
00508 template<typename T>
00509 ShFraction<T> rnd(const ShFraction<T> &a)
00510 {
00511 T ONE = ShFraction<T>::ONE;
00512 T HALF = ONE >> 1;
00513 T result;
00514 if(a.m_val > HALF) {
00515 result = ONE;
00516 } else if(!ShFraction<T>::is_signed || result > -HALF) {
00517 result = 0;
00518 } else {
00519 result = -ONE;
00520 }
00521 return ShFraction<T>(result);
00522 }
00523
00524 template<typename T>
00525 ShFraction<T> abs(const ShFraction<T> &a)
00526 {
00527 return ShFraction<T>(a.m_val < 0 ? -a.m_val: a.m_val);
00528 }
00529
00531 template<typename T>
00532 ShFraction<T> cond(const ShFraction<T> &a, const ShFraction<T> &b,
00533 const ShFraction<T> &c)
00534 {
00535 return ShFraction<T>(a.m_val > 0 ? b.m_val: c.m_val);
00536 }
00537
00538 template<typename T>
00539 ShFraction<T> lerp(const ShFraction<T> &a, const ShFraction<T> &b, const ShFraction<T> &c)
00540 {
00541 T ONE = ShFraction<T>(ShFraction<T>::ONE);
00542 return a * b + (ONE - a) * c;
00543 }
00544
00545 #undef _CompType
00546 #undef _LongType
00547 #undef _SignedLongType
00548 }
00549
00550 #endif