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