00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00034
00035 template<typename T>
00036 ShFraction<T>::ShFraction()
00037 {}
00038
00039 template<typename T>
00040 ShFraction<T>::ShFraction(double value)
00041 : m_val(clamp_val(value))
00042 {
00043 }
00044
00045 template<typename T>
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>
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>
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>
00070 ShFraction<T>::operator double() const
00071 {
00072 return get_double();
00073 }
00074
00075 template<typename T>
00076 T& ShFraction<T>::val()
00077 {
00078 return m_val;
00079 }
00080
00081 template<typename T>
00082 T ShFraction<T>::val() const
00083 {
00084 return m_val;
00085 }
00086
00088 template<typename T>
00089 ShFraction<T>& ShFraction<T>::operator=(double value)
00090 {
00091 m_val = clamp_val(value);
00092 return *this;
00093 }
00094
00095 template<typename T>
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>
00103 ShFraction<T>& ShFraction<T>::operator+=(double value)
00104 {
00105 return operator+=(ShFraction(value));
00106 }
00107
00108 template<typename T>
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>
00116 ShFraction<T>& ShFraction<T>::operator-=(double value)
00117 {
00118 return operator-=(ShFraction(value));
00119 }
00120
00121 template<typename T>
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>
00129 ShFraction<T>& ShFraction<T>::operator*=(double value)
00130 {
00131 return operator*=(ShFraction(value));
00132 }
00133
00134 template<typename T>
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>
00142 ShFraction<T>& ShFraction<T>::operator/=(double value)
00143 {
00144 return operator/=(ShFraction(value));
00145 }
00146
00147 template<typename T>
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>
00157 ShFraction<T>& ShFraction<T>::operator%=(double value)
00158 {
00159 return operator%=(ShFraction(value));
00160 }
00161
00162 template<typename T>
00163 ShFraction<T>& ShFraction<T>::operator%=(const ShFraction& other)
00164 {
00165
00166 m_val = m_val % other.m_val;
00167 if(m_val < 0) m_val += other.m_val;
00168 }
00169
00171 template<typename T>
00172 ShFraction<T> ShFraction<T>::operator-() const
00173 {
00174 if(is_signed ) 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>
00195 inline
00196 double ShFraction<T>::get_double() const
00197 {
00198 return double(m_val) / double(ONE);
00199 }
00200
00201 template<typename T>
00202 inline
00203 T ShFraction<T>::clamp_val(double value)
00204 {
00205 double temp = value * ONE;
00206
00207
00208 temp = std::max(std::min(temp, double(MAX)), double(MIN));
00209
00210 return T(temp);
00211 }
00212
00213 template<typename T>
00214 inline
00215 T ShFraction<T>::clamp_val(CompType value)
00216 {
00217
00218 value = std::max(std::min(value, CompType(MAX)), CompType(MIN));
00219
00220 return T(value);
00221 }
00222
00223 template<typename T>
00224 inline
00225 T ShFraction<T>::clamp_val_signed(SignedLongType value)
00226 {
00227
00228 value = std::max(std::min(value, SignedLongType(MAX)), SignedLongType(MIN));
00229
00230 return T(value);
00231 }
00232
00234 template<typename T>
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>
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>
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>
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>
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>
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>
00281 ShFraction<T> exp(const ShFraction<T> &a)
00282 {
00283 return ShFraction<T>(std::exp(double(a)));
00284 }
00285
00286
00287 template<typename T>
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>
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>
00302 ShFraction<T> log(const ShFraction<T> &a)
00303 {
00304 return ShFraction<T>(std::log(double(a)));
00305 }
00306
00307
00308 template<typename T>
00309 ShFraction<T> log2(const ShFraction<T> &a)
00310 {
00311 return ShFraction<T>(log2f(double(a)));
00312 }
00313
00314
00315 template<typename T>
00316 ShFraction<T> log10(const ShFraction<T> &a)
00317 {
00318 return ShFraction<T>(log10f(double(a)));
00319 }
00320
00321 template<typename T>
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>
00332 ShFraction<T> fmod(const ShFraction<T> &a, const ShFraction<T> &b)
00333 {
00334 return a % b;
00335 }
00336
00337
00338 template<typename T>
00339 ShFraction<T> pow(const ShFraction<T> &a, const ShFraction<T> &b)
00340 {
00341
00342
00343 return ShFraction<T>(std::pow(double(a), double(b)));
00344 }
00345
00346
00347
00348
00349 template<typename T>
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>
00357 ShFraction<T> rsq(const ShFraction<T> &a)
00358 {
00359 return rcp(a);
00360 }
00361
00362 template<typename T>
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>
00369 ShFraction<T> sqrt(const ShFraction<T> &a)
00370 {
00371 return ShFraction<T>(std::sqrt(double(a)));
00372 }
00373
00374
00376 template<typename T>
00377 ShFraction<T> acos(const ShFraction<T> &a)
00378 {
00379 return ShFraction<T>(std::acos(double(a)));
00380 }
00381
00382
00383 template<typename T>
00384 ShFraction<T> asin(const ShFraction<T> &a)
00385 {
00386 return ShFraction<T>(std::asin(double(a)));
00387 }
00388
00389
00390 template<typename T>
00391 ShFraction<T> atan(const ShFraction<T> &a)
00392 {
00393 return ShFraction<T>(std::atan(double(a)));
00394 }
00395
00396
00397 template<typename T>
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>
00405 ShFraction<T> cos(const ShFraction<T> &a)
00406 {
00407 return ShFraction<T>(std::cos(double(a)));
00408 }
00409
00410 template<typename T>
00411 ShFraction<T> sin(const ShFraction<T> &a)
00412 {
00413 return ShFraction<T>(std::sin(double(a)));
00414 }
00415
00416
00417 template<typename T>
00418 ShFraction<T> tan(const ShFraction<T> &a)
00419 {
00420 return ShFraction<T>(std::tan(double(a)));
00421 }
00422
00423
00425 template<typename T>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
00502 ShFraction<T> rnd(const ShFraction<T> &a)
00503 {
00504 T ONE = ShFraction<T>::ONE;
00505 T HALF = ONE >> 1;
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>
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>
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>
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