├── LICENSE ├── README.md └── fixedpoint.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006 Manuel Bua 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any 5 | damages arising from the use of this software. Permission is 6 | granted to anyone to use this software for any purpose, including 7 | commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 1. The origin of this software must not be misrepresented; you must 11 | not claim that you wrote the original software. If you use this 12 | software in a product, an acknowledgment in the product 13 | documentation would be appreciated but is not required. 14 | 15 | 2. Altered source versions must be plainly marked as such, and must 16 | not be misrepresented as being the original software. 17 | 18 | 3. This notice may not be removed or altered from any source 19 | distribution. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Fixed-point arithmetic in C++ 2 | 3 | Some pet-projects ago, i got hooked up by fixed-point arithmetic and its usefullness on the mobile platform where GPUs and multiple cores weren't that ubiquitous. 4 | 5 | While experimenting with the traditional implementations such as [this one](http://people.ece.cornell.edu/land/courses/ece4760/Math/) or this [other one](http://stackoverflow.com/questions/79677/whats-the-best-way-to-do-fixed-point-math), i wanted to try an object-oriented approach and this is the result. 6 | 7 | At that time, a more traditional-style implementation (#defines-based) was really faster than the object-oriented one, obviously the overhead was larger than the gain, but it was an interesting experiment nonetheless. 8 | 9 | ### Usage 10 | 11 | The class itself predefines both the 24.8 and the 16.16 formats: 12 | 13 | typedef FixedPoint< 8, LowPrecision, LowPrecision> fixed8_t; 14 | typedef FixedPoint<16, HighPrecision, HighPrecision> fixed16_t; 15 | 16 | An usage example coult be a generic, datatype-unaware *matrix* implementation: 17 | 18 | template 19 | class matrix { 20 | private: 21 | Number m[4][4]; 22 | 23 | public: 24 | matrix(); 25 | 26 | // matrix indexing 27 | inline Number operator()(const int,const int); 28 | 29 | // matrix operations 30 | matrix operator*(const matrix); 31 | matrix operator/(const matrix); 32 | }; 33 | 34 | Then you should be able to declare your test *matrix* types like this: 35 | 36 | matrix float_matrix; 37 | matrix fixed_matrix; -------------------------------------------------------------------------------- /fixedpoint.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2006 Manuel Bua 3 | * 4 | * THIS SOFTWARE IS PROVIDED 'AS-IS', WITHOUT ANY EXPRESS OR IMPLIED 5 | * WARRANTY. IN NO EVENT WILL THE AUTHORS BE HELD LIABLE FOR ANY DAMAGES 6 | * ARISING FROM THE USE OF THIS SOFTWARE. 7 | * 8 | * Permission is granted to anyone to use this software for any purpose, 9 | * including commercial applications, and to alter it and redistribute it 10 | * freely, subject to the following restrictions: 11 | * 12 | * 1. The origin of this software must not be misrepresented; you must not 13 | * claim that you wrote the original software. If you use this software 14 | * in a product, an acknowledgment in the product documentation would be 15 | * appreciated but is not required. 16 | * 17 | * 2. Altered source versions must be plainly marked as such, and must not 18 | * be misrepresented as being the original software. 19 | * 20 | * 3. This notice may not be removed or altered from any source 21 | * distribution. 22 | * 23 | */ 24 | 25 | #ifndef FIXEDPOINT_H 26 | #define FIXEDPOINT_H 27 | 28 | #include 29 | 30 | 31 | namespace fastmath 32 | { 33 | 34 | /** 35 | * Mantains precalculated basic information such 36 | * as bit-masks and other constants. 37 | */ 38 | template 39 | class FixedPointInfo 40 | { 41 | protected: 42 | enum { FRACTION_MASK = ( 1 << precision_bits ) - 1 }; 43 | enum { ONE = ( 1 << precision_bits ) }; 44 | enum { ROUND = ( 1 << ( precision_bits - 1 ) ) }; 45 | enum { HALF_BITS = ( precision_bits / 2 ) }; 46 | enum { SIGN_BIT = ( 1 << 31 ) }; 47 | }; 48 | 49 | 50 | /** 51 | * More comments for me ... 52 | */ 53 | template class MulPrecisionPolicy, 55 | template class DivPrecisionPolicy> 56 | class FixedPoint : public FixedPointInfo 57 | { 58 | public: 59 | 60 | 61 | /** 62 | * Construction w/ precision conversion 63 | */ 64 | template class mulP, template class divP> 65 | explicit FixedPoint( const FixedPoint& rhs ) 66 | { 67 | v = translate( rhs.v, bits ); 68 | } 69 | 70 | 71 | /** 72 | * Assignment w/ precision conversion 73 | * 74 | * \think 75 | * remove because subtle ambiguities? 76 | */ 77 | template class mulP, template class divP> 78 | inline FixedPoint& operator=( const FixedPoint& rhs ) 79 | { 80 | v = translate( rhs.v, bits ); 81 | return *this; 82 | } 83 | 84 | 85 | /** Construction */ 86 | inline static FixedPoint fromRaw( int32_t raw ) { FixedPoint tmp; tmp.v = raw; return tmp; } 87 | FixedPoint() : v( 0 ) {} 88 | FixedPoint( const FixedPoint& rhs ) : v( rhs.v ) {} 89 | explicit FixedPoint( float_t rhs ) : v( (int32_t)( rhs * (float_t)ONE + ( rhs < 0 ? -0.5f : 0.5f ) ) ) {} 90 | explicit FixedPoint( double_t rhs ) : v( (int32_t)( rhs * (double_t)ONE + ( rhs < 0 ? -0.5f : 0.5f ) ) ) {} 91 | explicit FixedPoint( int32_t rhs ) : v( rhs << precision_bits ) {} 92 | 93 | /** FixedPoint assignment */ 94 | inline FixedPoint& operator=( const FixedPoint& rhs ) { v = rhs.v; return *this; } 95 | inline FixedPoint& operator+=( const FixedPoint& rhs ) { v += rhs.v; return *this; } 96 | inline FixedPoint& operator-=( const FixedPoint& rhs ) { v -= rhs.v; return *this; } 97 | //inline FixedPoint& operator*=( const FixedPoint& rhs ) { v = mul_t::mul( v, rhs.v ); return *this; } 98 | //inline FixedPoint& operator/=( const FixedPoint& rhs ) { v = div_t::div( v, rhs.v ); return *this; } 99 | inline FixedPoint& operator*=( const FixedPoint& rhs ) { v = MulPrecisionPolicy::mul( v, rhs.v ); return *this; } 100 | inline FixedPoint& operator/=( const FixedPoint& rhs ) { v = DivPrecisionPolicy::div( v, rhs.v ); return *this; } 101 | 102 | /** int32_t assignment */ 103 | inline FixedPoint& operator=( int32_t rhs ) { v = FixedPoint( rhs ).v; return *this; } 104 | inline FixedPoint& operator+=( int32_t rhs ) { v += rhs << precision_bits; return *this; } 105 | inline FixedPoint& operator-=( int32_t rhs ) { v -= rhs << precision_bits; return *this; } 106 | inline FixedPoint& operator*=( int32_t rhs ) { v *= rhs; return *this; } 107 | inline FixedPoint& operator/=( int32_t rhs ) { v /= rhs; return *this; } 108 | 109 | /** float_t assignment */ 110 | inline FixedPoint& operator=( float_t rhs ) { v = FixedPoint( rhs ).v; return *this; } 111 | inline FixedPoint& operator+=( float_t rhs ) { v += FixedPoint( rhs ).v; return *this; } 112 | inline FixedPoint& operator-=( float_t rhs ) { v -= FixedPoint( rhs ).v; return *this; } 113 | inline FixedPoint& operator*=( float_t rhs ) { *this *= FixedPoint( rhs ); return *this; } 114 | inline FixedPoint& operator/=( float_t rhs ) { *this /= FixedPoint( rhs ); return *this; } 115 | 116 | /** double_t assignment */ 117 | inline FixedPoint& operator=( double_t rhs ) { v = FixedPoint( rhs ).v; return *this; } 118 | inline FixedPoint& operator+=( double_t rhs ) { v += FixedPoint( rhs ).v; return *this; } 119 | inline FixedPoint& operator-=( double_t rhs ) { v -= FixedPoint( rhs ).v; return *this; } 120 | inline FixedPoint& operator*=( double_t rhs ) { *this *= FixedPoint( rhs ); return *this; } 121 | inline FixedPoint& operator/=( double_t rhs ) { *this /= FixedPoint( rhs ); return *this; } 122 | 123 | /** shift assignment */ 124 | inline FixedPoint& operator<<=( int32_t shift ) { v <<= shift; return *this; } 125 | inline FixedPoint& operator>>=( int32_t shift ) { v >>= shift; return *this; } 126 | 127 | /** converters */ 128 | inline operator int32_t() { return v >> precision_bits; } 129 | inline operator float_t() { return v * ( 1.0f / static_cast( ONE ) ); } 130 | inline operator double_t() { return v * ( 1.0f / static_cast( ONE ) ); } 131 | 132 | 133 | /** 134 | * Gives access to the integer part of the number. 135 | * 136 | * An use of the integer portion could be for lerping fixed-point 137 | * quantities. 138 | */ 139 | inline int32_t getInteger() const { return( v >> precision_bits ); } 140 | 141 | /** 142 | * Gives access to the fractional part of the number. 143 | */ 144 | inline uint32_t getFraction() const { return( v & FRACTION_MASK ); } 145 | 146 | inline int32_t getRaw() const { return v; } 147 | 148 | /** Unary operators */ 149 | inline FixedPoint operator+() const { return FixedPoint::fromRaw( v ); } 150 | inline FixedPoint operator-() const { return FixedPoint::fromRaw( -v ); } 151 | 152 | 153 | /** Comparison operators */ 154 | 155 | // FixedPoint 156 | inline bool_t operator==( const FixedPoint& other ) { return v == other.v; } 157 | inline bool_t operator!=( const FixedPoint& other ) { return v != other.v; } 158 | inline bool_t operator<( const FixedPoint& other ) { return v < other.v; } 159 | inline bool_t operator>( const FixedPoint& other ) { return v > other.v; } 160 | inline bool_t operator<=( const FixedPoint& other ) { return v <= other.v; } 161 | inline bool_t operator>=( const FixedPoint& other ) { return v >= other.v; } 162 | 163 | // int32_t 164 | inline bool_t operator==( int32_t other ) { return v == FixedPoint( other ).v; } 165 | inline bool_t operator!=( int32_t other ) { return v != FixedPoint( other ).v; } 166 | inline bool_t operator<( int32_t other ) { return v < FixedPoint( other ).v; } 167 | inline bool_t operator>( int32_t other ) { return v > FixedPoint( other ).v; } 168 | inline bool_t operator<=( int32_t other ) { return v <= FixedPoint( other ).v; } 169 | inline bool_t operator>=( int32_t other ) { return v >= FixedPoint( other ).v; } 170 | 171 | // float 172 | inline bool_t operator==( float_t other ) { return v == FixedPoint( other ).v; } 173 | inline bool_t operator!=( float_t other ) { return v != FixedPoint( other ).v; } 174 | inline bool_t operator<( float_t other ) { return v < FixedPoint( other ).v; } 175 | inline bool_t operator>( float_t other ) { return v > FixedPoint( other ).v; } 176 | inline bool_t operator<=( float_t other ) { return v <= FixedPoint( other ).v; } 177 | inline bool_t operator>=( float_t other ) { return v >= FixedPoint( other ).v; } 178 | 179 | // double 180 | inline bool_t operator==( double_t other ) { return v == FixedPoint( other ).v; } 181 | inline bool_t operator!=( double_t other ) { return v != FixedPoint( other ).v; } 182 | inline bool_t operator<( double_t other ) { return v < FixedPoint( other ).v; } 183 | inline bool_t operator>( double_t other ) { return v > FixedPoint( other ).v; } 184 | inline bool_t operator<=( double_t other ) { return v <= FixedPoint( other ).v; } 185 | inline bool_t operator>=( double_t other ) { return v >= FixedPoint( other ).v; } 186 | 187 | 188 | /** Utilities */ 189 | /* 190 | inline FixedPoint mulDiv( const FixedPoint& m1, const FixedPoint& m2, const FixedPoint& d ) 191 | { 192 | int64_t t = int64_t( m1 ) * int64_t( m2 ); 193 | t += static_cast( ROUND ); 194 | t /= d; 195 | return int32_t(t); 196 | } 197 | */ 198 | inline FixedPoint abs() 199 | { 200 | return FixedPoint::fromRaw( ( v & ( 1 << 31 ) ) ? -v : v ); 201 | } 202 | 203 | inline FixedPoint sign() 204 | { 205 | return FixedPoint::fromRaw( ( v & ( 1 << 31 ) ) ? -static_cast( ONE ): static_cast( ONE ) ); 206 | } 207 | 208 | inline FixedPoint floor() 209 | { 210 | return FixedPoint( (int32_t)( v >> precision_bits ) ); 211 | } 212 | 213 | inline FixedPoint ceil() 214 | { 215 | int32_t tmp = -( -v >> precision_bits ); 216 | return FixedPoint( tmp ); 217 | } 218 | 219 | inline FixedPoint round() 220 | { 221 | int64_t tmp = int64_t( v ); 222 | if( tmp > 0 ) tmp += static_cast( ROUND ); else tmp-= static_cast( ROUND ); 223 | tmp /= static_cast( ONE ); 224 | return FixedPoint( int32_t( tmp ) ); 225 | } 226 | 227 | 228 | private: 229 | 230 | int32_t v; 231 | 232 | inline static int32_t translate( int32_t src, int32_t bits ) 233 | { 234 | if( bits < precision_bits ) 235 | { 236 | return( src << ( precision_bits - bits ) ); 237 | } 238 | else 239 | { 240 | return( src >> ( bits - precision_bits ) ); 241 | } 242 | } 243 | 244 | 245 | //friend FixedPoint<0>; friend FixedPoint<1>; friend FixedPoint<2>; friend FixedPoint<3>; 246 | //friend FixedPoint<4>; friend FixedPoint<5>; friend FixedPoint<6>; friend FixedPoint<7>; 247 | //friend FixedPoint<8>; friend FixedPoint<9>; friend FixedPoint<10>; friend FixedPoint<11>; 248 | //friend FixedPoint<12>; friend FixedPoint<13>; friend FixedPoint<14>; friend FixedPoint<15>; 249 | //friend FixedPoint<16>; friend FixedPoint<17>; friend FixedPoint<18>; friend FixedPoint<19>; 250 | //friend FixedPoint<20>; friend FixedPoint<21>; friend FixedPoint<22>; friend FixedPoint<23>; 251 | //friend FixedPoint<24>; friend FixedPoint<25>; friend FixedPoint<26>; friend FixedPoint<27>; 252 | //friend FixedPoint<28>; friend FixedPoint<29>; friend FixedPoint<30>; friend FixedPoint<31>; 253 | }; 254 | 255 | 256 | ////////////////////////////////////////////////////////////////////////// 257 | // "Add" operation on FixedPoint (global) 258 | ////////////////////////////////////////////////////////////////////////// 259 | 260 | 261 | // op: FixedPoint + FixedPoint 262 | template class mulP, template class divP> 263 | inline FixedPoint operator+( const FixedPoint& lhs, const FixedPoint& rhs ) 264 | { 265 | FixedPoint result( lhs ); 266 | result += rhs; 267 | return result; 268 | } 269 | 270 | 271 | /** 272 | * int32_t 273 | */ 274 | 275 | // op: FixedPoint + int32_t 276 | template class mulP, template class divP> 277 | inline FixedPoint operator+( const FixedPoint& lhs, int32_t rhs ) 278 | { 279 | FixedPoint result( lhs ); 280 | result += rhs; 281 | return result; 282 | } 283 | 284 | // op: int32_t + FixedPoint 285 | template class mulP, template class divP> 286 | inline FixedPoint operator+( int32_t lhs, const FixedPoint& rhs ) 287 | { 288 | return rhs + lhs; 289 | } 290 | 291 | 292 | /** 293 | * float_t 294 | */ 295 | 296 | // op: FixedPoint + float_t 297 | template class mulP, template class divP> 298 | inline FixedPoint operator+( const FixedPoint& lhs, float_t rhs ) 299 | { 300 | FixedPoint result( lhs ); 301 | result += rhs; 302 | return result; 303 | } 304 | 305 | // op: float_t + FixedPoint 306 | template class mulP, template class divP> 307 | inline FixedPoint operator+( float_t lhs, const FixedPoint& rhs ) 308 | { 309 | return rhs + lhs; 310 | } 311 | 312 | 313 | /** 314 | * double_t 315 | */ 316 | 317 | // op: FixedPoint + double_t 318 | template class mulP, template class divP> 319 | inline FixedPoint operator+( const FixedPoint& lhs, double_t rhs ) 320 | { 321 | FixedPoint result( lhs ); 322 | result += rhs; 323 | return result; 324 | } 325 | 326 | // op: double_t + FixedPoint 327 | template class mulP, template class divP> 328 | inline FixedPoint operator+( double_t lhs, const FixedPoint& rhs ) 329 | { 330 | return rhs + lhs; 331 | } 332 | 333 | 334 | ////////////////////////////////////////////////////////////////////////// 335 | // "Subtract" operation on FixedPoint (global) 336 | ////////////////////////////////////////////////////////////////////////// 337 | 338 | 339 | // op: FixedPoint - FixedPoint 340 | template class mulP, template class divP> 341 | inline FixedPoint operator-( const FixedPoint& lhs, const FixedPoint& rhs ) 342 | { 343 | FixedPoint result( lhs ); 344 | result -= rhs; 345 | return result; 346 | } 347 | 348 | 349 | /** 350 | * int32_t 351 | */ 352 | 353 | // op: FixedPoint - int32_t 354 | template class mulP, template class divP> 355 | inline FixedPoint operator-( const FixedPoint& lhs, int32_t rhs ) 356 | { 357 | FixedPoint result( lhs ); 358 | result -= rhs; 359 | return result; 360 | } 361 | 362 | // op: int32_t - FixedPoint 363 | template class mulP, template class divP> 364 | inline FixedPoint operator-( int32_t lhs, const FixedPoint& rhs ) 365 | { 366 | return FixedPoint( lhs ) - rhs; 367 | } 368 | 369 | 370 | /** 371 | * float_t 372 | */ 373 | 374 | // op: FixedPoint - float_t 375 | template class mulP, template class divP> 376 | inline FixedPoint operator-( const FixedPoint& lhs, float_t rhs ) 377 | { 378 | FixedPoint result( lhs ); 379 | result -= rhs; 380 | return result; 381 | } 382 | 383 | // op: float_t - FixedPoint 384 | template class mulP, template class divP> 385 | inline FixedPoint operator-( float_t lhs, const FixedPoint& rhs ) 386 | { 387 | return FixedPoint( lhs ) - rhs; 388 | } 389 | 390 | 391 | /** 392 | * double_t 393 | */ 394 | 395 | // op: FixedPoint - double_t 396 | template class mulP, template class divP> 397 | inline FixedPoint operator-( const FixedPoint& lhs, double_t rhs ) 398 | { 399 | FixedPoint result( lhs ); 400 | result -= rhs; 401 | return result; 402 | } 403 | 404 | // op: double_t - FixedPoint 405 | template class mulP, template class divP> 406 | inline FixedPoint operator-( double_t lhs, const FixedPoint& rhs ) 407 | { 408 | return FixedPoint( lhs ) - rhs; 409 | } 410 | 411 | 412 | ////////////////////////////////////////////////////////////////////////// 413 | // "Multiply" operation on FixedPoint (global) 414 | ////////////////////////////////////////////////////////////////////////// 415 | 416 | 417 | // op: FixedPoint * FixedPoint 418 | template class mulP, template class divP> 419 | inline FixedPoint operator*( const FixedPoint& lhs, const FixedPoint& rhs ) 420 | { 421 | FixedPoint result( lhs ); 422 | result *= rhs; 423 | return result; 424 | } 425 | 426 | 427 | /** 428 | * int32_t 429 | */ 430 | 431 | // op: FixedPoint * int32_t 432 | template class mulP, template class divP> 433 | inline FixedPoint operator*( const FixedPoint& lhs, int32_t rhs ) 434 | { 435 | FixedPoint result( lhs ); 436 | result *= rhs; 437 | return result; 438 | } 439 | 440 | // op: int32_t * FixedPoint 441 | template class mulP, template class divP> 442 | inline FixedPoint operator*( int32_t lhs, const FixedPoint& rhs ) 443 | { 444 | return rhs * lhs; 445 | } 446 | 447 | 448 | /** 449 | * float_t 450 | */ 451 | 452 | // op: FixedPoint * float_t 453 | template class mulP, template class divP> 454 | inline FixedPoint operator*( const FixedPoint& lhs, float_t rhs ) 455 | { 456 | FixedPoint result( lhs ); 457 | result *= rhs; 458 | return result; 459 | } 460 | 461 | // op: float_t * FixedPoint 462 | template class mulP, template class divP> 463 | inline FixedPoint operator*( float_t lhs, const FixedPoint& rhs ) 464 | { 465 | return rhs * lhs; 466 | } 467 | 468 | 469 | /** 470 | * double_t 471 | */ 472 | 473 | // op: FixedPoint * double_t 474 | template class mulP, template class divP> 475 | inline FixedPoint operator*( const FixedPoint& lhs, double_t rhs ) 476 | { 477 | FixedPoint result( lhs ); 478 | result *= rhs; 479 | return result; 480 | } 481 | 482 | // op: double_t * FixedPoint 483 | template class mulP, template class divP> 484 | inline FixedPoint operator*( double_t lhs, const FixedPoint& rhs ) 485 | { 486 | return rhs * lhs; 487 | } 488 | 489 | 490 | ////////////////////////////////////////////////////////////////////////// 491 | // "Division" operation on FixedPoint (global) 492 | ////////////////////////////////////////////////////////////////////////// 493 | 494 | 495 | // op: FixedPoint / FixedPoint 496 | template class mulP, template class divP> 497 | inline FixedPoint operator/( const FixedPoint& lhs, const FixedPoint& rhs ) 498 | { 499 | FixedPoint result( lhs ); 500 | result /= rhs; 501 | return result; 502 | } 503 | 504 | 505 | /** 506 | * int32_t 507 | */ 508 | 509 | // op: FixedPoint / int32_t 510 | template class mulP, template class divP> 511 | inline FixedPoint operator/( const FixedPoint& lhs, int32_t rhs ) 512 | { 513 | FixedPoint result( lhs ); 514 | result /= rhs; 515 | return result; 516 | } 517 | 518 | // op: int32_t / FixedPoint 519 | template class mulP, template class divP> 520 | inline FixedPoint operator/( int32_t lhs, const FixedPoint& rhs ) 521 | { 522 | return FixedPoint( lhs ) / rhs; 523 | } 524 | 525 | 526 | /** 527 | * float_t 528 | */ 529 | 530 | // op: FixedPoint / float_t 531 | template class mulP, template class divP> 532 | inline FixedPoint operator/( const FixedPoint& lhs, float_t rhs ) 533 | { 534 | FixedPoint result( lhs ); 535 | result /= rhs; 536 | return result; 537 | } 538 | 539 | // op: float_t / FixedPoint 540 | template class mulP, template class divP> 541 | inline FixedPoint operator/( float_t lhs, const FixedPoint& rhs ) 542 | { 543 | return FixedPoint( lhs ) / rhs; 544 | } 545 | 546 | 547 | /** 548 | * double_t 549 | */ 550 | 551 | // op: FixedPoint / double_t 552 | template class mulP, template class divP> 553 | inline FixedPoint operator/( const FixedPoint& lhs, double_t rhs ) 554 | { 555 | FixedPoint result( lhs ); 556 | result /= rhs; 557 | return result; 558 | } 559 | 560 | // op: double_t / FixedPoint 561 | template class mulP, template class divP> 562 | inline FixedPoint operator/( double_t lhs, const FixedPoint& rhs ) 563 | { 564 | return FixedPoint( lhs ) / rhs; 565 | } 566 | 567 | 568 | ////////////////////////////////////////////////////////////////////////// 569 | // Shift operators 570 | ////////////////////////////////////////////////////////////////////////// 571 | 572 | template class mulP, template class divP> 573 | inline FixedPoint operator<<( const FixedPoint& x, int32_t shift ) 574 | { 575 | FixedPoint result( x ); 576 | result <<= shift; 577 | return result; 578 | } 579 | 580 | template class mulP, template class divP> 581 | inline FixedPoint operator>>( const FixedPoint& x, int32_t shift ) 582 | { 583 | FixedPoint result( x ); 584 | result >>= shift; 585 | return result; 586 | } 587 | 588 | 589 | ////////////////////////////////////////////////////////////////////////// 590 | // Comparison operators 591 | ////////////////////////////////////////////////////////////////////////// 592 | 593 | // FixedPoint 594 | template class mulP, template class divP> inline bool_t operator==( const FixedPoint& lhs, const FixedPoint& rhs ) { return lhs == rhs; } 595 | template class mulP, template class divP> inline bool_t operator!=( const FixedPoint& lhs, const FixedPoint& rhs ) { return lhs != rhs; } 596 | template class mulP, template class divP> inline bool_t operator<( const FixedPoint& lhs, const FixedPoint& rhs ) { return lhs < rhs; } 597 | template class mulP, template class divP> inline bool_t operator<=( const FixedPoint& lhs, const FixedPoint& rhs ) { return lhs <= rhs; } 598 | template class mulP, template class divP> inline bool_t operator>( const FixedPoint& lhs, const FixedPoint& rhs ) { return lhs > rhs; } 599 | template class mulP, template class divP> inline bool_t operator>=( const FixedPoint& lhs, const FixedPoint& rhs ) { return lhs >= rhs; } 600 | 601 | // int32_t 602 | template class mulP, template class divP> inline bool_t operator==( int32_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) == rhs; } 603 | template class mulP, template class divP> inline bool_t operator!=( int32_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) != rhs; } 604 | template class mulP, template class divP> inline bool_t operator<( int32_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) < rhs; } 605 | template class mulP, template class divP> inline bool_t operator<=( int32_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) <= rhs; } 606 | template class mulP, template class divP> inline bool_t operator>( int32_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) > rhs; } 607 | template class mulP, template class divP> inline bool_t operator>=( int32_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) >= rhs; } 608 | template class mulP, template class divP> inline bool_t operator==( const FixedPoint& lhs, int32_t rhs ) { return lhs == FixedPoint( rhs ); } 609 | template class mulP, template class divP> inline bool_t operator!=( const FixedPoint& lhs, int32_t rhs ) { return lhs != FixedPoint( rhs ); } 610 | template class mulP, template class divP> inline bool_t operator<( const FixedPoint& lhs, int32_t rhs ) { return lhs < FixedPoint( rhs ); } 611 | template class mulP, template class divP> inline bool_t operator<=( const FixedPoint& lhs, int32_t rhs ) { return lhs <= FixedPoint( rhs ); } 612 | template class mulP, template class divP> inline bool_t operator>( const FixedPoint& lhs, int32_t rhs ) { return lhs > FixedPoint( rhs ); } 613 | template class mulP, template class divP> inline bool_t operator>=( const FixedPoint& lhs, int32_t rhs ) { return lhs >= FixedPoint( rhs ); } 614 | 615 | // float_t 616 | template class mulP, template class divP> inline bool_t operator==( float_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) == rhs; } 617 | template class mulP, template class divP> inline bool_t operator!=( float_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) != rhs; } 618 | template class mulP, template class divP> inline bool_t operator<( float_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) < rhs; } 619 | template class mulP, template class divP> inline bool_t operator<=( float_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) <= rhs; } 620 | template class mulP, template class divP> inline bool_t operator>( float_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) > rhs; } 621 | template class mulP, template class divP> inline bool_t operator>=( float_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) >= rhs; } 622 | template class mulP, template class divP> inline bool_t operator==( const FixedPoint& lhs, float_t rhs ) { return lhs == FixedPoint( rhs ); } 623 | template class mulP, template class divP> inline bool_t operator!=( const FixedPoint& lhs, float_t rhs ) { return lhs != FixedPoint( rhs ); } 624 | template class mulP, template class divP> inline bool_t operator<( const FixedPoint& lhs, float_t rhs ) { return lhs < FixedPoint( rhs ); } 625 | template class mulP, template class divP> inline bool_t operator<=( const FixedPoint& lhs, float_t rhs ) { return lhs <= FixedPoint( rhs ); } 626 | template class mulP, template class divP> inline bool_t operator>( const FixedPoint& lhs, float_t rhs ) { return lhs > FixedPoint( rhs ); } 627 | template class mulP, template class divP> inline bool_t operator>=( const FixedPoint& lhs, float_t rhs ) { return lhs >= FixedPoint( rhs ); } 628 | 629 | // double_t 630 | template class mulP, template class divP> inline bool_t operator==( double_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) == rhs; } 631 | template class mulP, template class divP> inline bool_t operator!=( double_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) != rhs; } 632 | template class mulP, template class divP> inline bool_t operator<( double_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) < rhs; } 633 | template class mulP, template class divP> inline bool_t operator<=( double_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) <= rhs; } 634 | template class mulP, template class divP> inline bool_t operator>( double_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) > rhs; } 635 | template class mulP, template class divP> inline bool_t operator>=( double_t lhs, const FixedPoint& rhs ) { return FixedPoint( lhs ) >= rhs; } 636 | template class mulP, template class divP> inline bool_t operator==( const FixedPoint& lhs, double_t rhs ) { return lhs == FixedPoint( rhs ); } 637 | template class mulP, template class divP> inline bool_t operator!=( const FixedPoint& lhs, double_t rhs ) { return lhs != FixedPoint( rhs ); } 638 | template class mulP, template class divP> inline bool_t operator<( const FixedPoint& lhs, double_t rhs ) { return lhs < FixedPoint( rhs ); } 639 | template class mulP, template class divP> inline bool_t operator<=( const FixedPoint& lhs, double_t rhs ) { return lhs <= FixedPoint( rhs ); } 640 | template class mulP, template class divP> inline bool_t operator>( const FixedPoint& lhs, double_t rhs ) { return lhs > FixedPoint( rhs ); } 641 | template class mulP, template class divP> inline bool_t operator>=( const FixedPoint& lhs, double_t rhs ) { return lhs >= FixedPoint( rhs ); } 642 | 643 | 644 | ////////////////////////////////////////////////////////////////////////// 645 | // Other assignments 646 | ////////////////////////////////////////////////////////////////////////// 647 | 648 | // int32_t 649 | template class mulP, template class divP> inline int32_t& operator+=( int32_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs + rhs; return lhs; } 650 | template class mulP, template class divP> inline int32_t& operator-=( int32_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs - rhs; return lhs; } 651 | template class mulP, template class divP> inline int32_t& operator*=( int32_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs * rhs; return lhs; } 652 | template class mulP, template class divP> inline int32_t& operator/=( int32_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs / rhs; return lhs; } 653 | 654 | // float_t 655 | template class mulP, template class divP> inline float_t& operator+=( float_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs + rhs; return lhs; } 656 | template class mulP, template class divP> inline float_t& operator-=( float_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs - rhs; return lhs; } 657 | template class mulP, template class divP> inline float_t& operator*=( float_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs * rhs; return lhs; } 658 | template class mulP, template class divP> inline float_t& operator/=( float_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs / rhs; return lhs; } 659 | 660 | // double_t 661 | template class mulP, template class divP> inline double_t& operator+=( double_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs + rhs; return lhs; } 662 | template class mulP, template class divP> inline double_t& operator-=( double_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs - rhs; return lhs; } 663 | template class mulP, template class divP> inline double_t& operator*=( double_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs * rhs; return lhs; } 664 | template class mulP, template class divP> inline double_t& operator/=( double_t& lhs, const FixedPoint& rhs) { lhs = (FixedPoint)lhs / rhs; return lhs; } 665 | 666 | 667 | 668 | // local helpers 669 | inline int32_t neg( int32_t r ) { return (r >> 31); } 670 | 671 | 672 | /////////////////////////////////////////////////////////////////////// 673 | // High-precision policies (int64_t) 674 | /////////////////////////////////////////////////////////////////////// 675 | 676 | template 677 | class HighPrecision : public FixedPointInfo 678 | { 679 | public: 680 | 681 | inline static int32_t mul( int32_t l, int32_t r ) 682 | { 683 | int64_t t = int64_t(l) * int64_t(r); 684 | t += static_cast( ROUND ); 685 | t >>= bits; 686 | return int32_t(t); 687 | 688 | /* 689 | int64_t tmp32_32; 690 | int32_t res16_16; 691 | tmp32_32 = l; 692 | tmp32_32 *= r; 693 | // result is now 32:32 694 | tmp32_32 >>= 16; // chop off the lower 16 bits 695 | res16_16 = ( int ) tmp32_32; // chop off the upper 16bits. 696 | // result is now back at 16:16 697 | return res16_16; 698 | */ 699 | } 700 | 701 | inline static int32_t div( int32_t l, int32_t r ) 702 | { 703 | int64_t t = int64_t(l) << bits; 704 | int32_t q = int32_t( t / r ); 705 | int32_t rem = int32_t( t % r ); 706 | q += 1 + neg( (int32_t)( (rem << 1 ) - r ) ); 707 | return q; 708 | } 709 | 710 | /* 711 | inline static int32_t mul( int32_t l, int32_t r ) 712 | 713 | { 714 | int64_t t = int64_t(l) * int64_t(r); 715 | t += static_cast( ROUND ); 716 | t >>= bits; 717 | return int32_t(t); 718 | } 719 | 720 | inline static int32_t div( int32_t l, int32_t r ) 721 | { 722 | int64_t t = int64_t(l) << bits; 723 | t /= r; 724 | return int32_t(t); 725 | } 726 | */ 727 | }; 728 | 729 | 730 | /////////////////////////////////////////////////////////////////////// 731 | // Mid-precision policies (int32_t) *UNSAFE* 732 | /////////////////////////////////////////////////////////////////////// 733 | 734 | // at now this is UNSAFE if going to overflow 735 | template 736 | class MidPrecision : public FixedPointInfo 737 | { 738 | public: 739 | 740 | inline static int32_t mul( int32_t l, int32_t r ) 741 | { 742 | register unsigned int a,b; 743 | register bool sign; 744 | 745 | int32_t a1 = l, b1 = r; 746 | 747 | sign = (a1 ^ b1) < 0; 748 | if (a1 < 0) {a1 = -a1;} 749 | if (b1 < 0) {b1 = -b1;} 750 | // a and b contain integer part 751 | // a1 and b1 contain fractional part. 752 | a = (((unsigned int)a1) >> bits); a1 &= ~(a << bits); 753 | b = (((unsigned int)b1) >> bits); b1 &= ~(b << bits); 754 | a1 = ((a*b) << bits) + (a*b1 + b*a1) + 755 | ((unsigned int)((a1*b1) + (1 << (bits-1))) >> bits); 756 | 757 | if (a1 < 0) {a1 ^= static_cast( SIGN_BIT );} 758 | if (sign) {a1 = -a1;} 759 | return a1; 760 | } 761 | 762 | inline static int32_t div( int32_t l, int32_t r ) 763 | { 764 | register int res, mask; 765 | register bool sign; 766 | 767 | int32_t a = l, b = r; 768 | 769 | sign = (a ^ b) < 0; 770 | if (a < 0) {a = -a;} 771 | if (b < 0) {b = -b;} 772 | mask = (1< b) {b <<= 1; mask <<= 1;} 774 | //while (mask != 0) 775 | while (mask > 0) 776 | { 777 | if (a >= b) {res |= mask; a -= b;} 778 | mask >>= 1; b >>= 1; 779 | } 780 | 781 | if (res < 0) {res ^= static_cast( SIGN_BIT );} 782 | if (sign) {res = -res;} 783 | return res; 784 | } 785 | 786 | }; 787 | 788 | 789 | /////////////////////////////////////////////////////////////////////// 790 | // Low-precision policies (int32_t) 791 | /////////////////////////////////////////////////////////////////////// 792 | 793 | template 794 | class LowPrecision : public FixedPointInfo 795 | { 796 | public: 797 | 798 | inline static int32_t mul( int32_t l, int32_t r ) 799 | { 800 | return ( ( l * r ) >> bits ); 801 | } 802 | 803 | inline static int32_t div( int32_t l, int32_t r ) 804 | { 805 | return( ( l << bits ) / r ); 806 | } 807 | 808 | }; 809 | 810 | 811 | // Predefines 812 | typedef FixedPoint< 8, LowPrecision, LowPrecision > fixed8_t; 813 | typedef FixedPoint< 16, HighPrecision, HighPrecision > fixed16_t; 814 | typedef fixed16_t fixed_t; 815 | 816 | } // end of namespace fastmath 817 | 818 | 819 | #endif // FIXEDPOINT_H --------------------------------------------------------------------------------