A fixed point library from Trenki http://www.trenki.net/content/view/17/1/ Slightly modified so that the fixed point data structure can automatically cast itself to float or int when used in an expression.
fixed_class.h@0:aa2871c4c041, 2010-10-20 (annotated)
- Committer:
- sravet
- Date:
- Wed Oct 20 02:20:46 2010 +0000
- Revision:
- 0:aa2871c4c041
First checkin.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sravet | 0:aa2871c4c041 | 1 | /* |
sravet | 0:aa2871c4c041 | 2 | Copyright (c) 2007, Markus Trenkwalder |
sravet | 0:aa2871c4c041 | 3 | |
sravet | 0:aa2871c4c041 | 4 | All rights reserved. |
sravet | 0:aa2871c4c041 | 5 | |
sravet | 0:aa2871c4c041 | 6 | Redistribution and use in source and binary forms, with or without |
sravet | 0:aa2871c4c041 | 7 | modification, are permitted provided that the following conditions are met: |
sravet | 0:aa2871c4c041 | 8 | |
sravet | 0:aa2871c4c041 | 9 | * Redistributions of source code must retain the above copyright notice, |
sravet | 0:aa2871c4c041 | 10 | this list of conditions and the following disclaimer. |
sravet | 0:aa2871c4c041 | 11 | |
sravet | 0:aa2871c4c041 | 12 | * Redistributions in binary form must reproduce the above copyright notice, |
sravet | 0:aa2871c4c041 | 13 | this list of conditions and the following disclaimer in the documentation |
sravet | 0:aa2871c4c041 | 14 | and/or other materials provided with the distribution. |
sravet | 0:aa2871c4c041 | 15 | |
sravet | 0:aa2871c4c041 | 16 | * Neither the name of the library's copyright owner nor the names of its |
sravet | 0:aa2871c4c041 | 17 | contributors may be used to endorse or promote products derived from this |
sravet | 0:aa2871c4c041 | 18 | software without specific prior written permission. |
sravet | 0:aa2871c4c041 | 19 | |
sravet | 0:aa2871c4c041 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
sravet | 0:aa2871c4c041 | 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
sravet | 0:aa2871c4c041 | 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
sravet | 0:aa2871c4c041 | 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
sravet | 0:aa2871c4c041 | 24 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
sravet | 0:aa2871c4c041 | 25 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
sravet | 0:aa2871c4c041 | 26 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
sravet | 0:aa2871c4c041 | 27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
sravet | 0:aa2871c4c041 | 28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
sravet | 0:aa2871c4c041 | 29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
sravet | 0:aa2871c4c041 | 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
sravet | 0:aa2871c4c041 | 31 | */ |
sravet | 0:aa2871c4c041 | 32 | |
sravet | 0:aa2871c4c041 | 33 | #ifndef FIXEDP_CLASS_H_INCLUDED |
sravet | 0:aa2871c4c041 | 34 | #define FIXEDP_CLASS_H_INCLUDED |
sravet | 0:aa2871c4c041 | 35 | |
sravet | 0:aa2871c4c041 | 36 | #ifdef _MSC_VER |
sravet | 0:aa2871c4c041 | 37 | #pragma once |
sravet | 0:aa2871c4c041 | 38 | #endif |
sravet | 0:aa2871c4c041 | 39 | |
sravet | 0:aa2871c4c041 | 40 | #include "fixed_func.h" |
sravet | 0:aa2871c4c041 | 41 | |
sravet | 0:aa2871c4c041 | 42 | namespace fixedpoint { |
sravet | 0:aa2871c4c041 | 43 | |
sravet | 0:aa2871c4c041 | 44 | // The template argument p in all of the following functions refers to the |
sravet | 0:aa2871c4c041 | 45 | // fixed point precision (e.g. p = 8 gives 24.8 fixed point functions). |
sravet | 0:aa2871c4c041 | 46 | |
sravet | 0:aa2871c4c041 | 47 | template <int p> |
sravet | 0:aa2871c4c041 | 48 | struct fixed_point { |
sravet | 0:aa2871c4c041 | 49 | int32_t intValue; |
sravet | 0:aa2871c4c041 | 50 | |
sravet | 0:aa2871c4c041 | 51 | fixed_point() {} |
sravet | 0:aa2871c4c041 | 52 | /*explicit*/ fixed_point(int32_t i) : intValue(i << p) {} |
sravet | 0:aa2871c4c041 | 53 | /*explicit*/ fixed_point(float f) : intValue(float2fix<p>(f)) {} |
sravet | 0:aa2871c4c041 | 54 | /*explicit*/ fixed_point(double f) : intValue(float2fix<p>((float)f)) {} |
sravet | 0:aa2871c4c041 | 55 | |
sravet | 0:aa2871c4c041 | 56 | fixed_point& operator += (fixed_point r) { intValue += r.intValue; return *this; } |
sravet | 0:aa2871c4c041 | 57 | fixed_point& operator -= (fixed_point r) { intValue -= r.intValue; return *this; } |
sravet | 0:aa2871c4c041 | 58 | fixed_point& operator *= (fixed_point r) { intValue = fixmul<p>(intValue, r.intValue); return *this; } |
sravet | 0:aa2871c4c041 | 59 | fixed_point& operator /= (fixed_point r) { intValue = fixdiv<p>(intValue, r.intValue); return *this; } |
sravet | 0:aa2871c4c041 | 60 | |
sravet | 0:aa2871c4c041 | 61 | fixed_point& operator *= (int32_t r) { intValue *= r; return *this; } |
sravet | 0:aa2871c4c041 | 62 | fixed_point& operator /= (int32_t r) { intValue /= r; return *this; } |
sravet | 0:aa2871c4c041 | 63 | |
sravet | 0:aa2871c4c041 | 64 | fixed_point operator - () const { fixed_point x; x.intValue = -intValue; return x; } |
sravet | 0:aa2871c4c041 | 65 | fixed_point operator + (fixed_point r) const { fixed_point x = *this; x += r; return x;} |
sravet | 0:aa2871c4c041 | 66 | fixed_point operator - (fixed_point r) const { fixed_point x = *this; x -= r; return x;} |
sravet | 0:aa2871c4c041 | 67 | fixed_point operator * (fixed_point r) const { fixed_point x = *this; x *= r; return x;} |
sravet | 0:aa2871c4c041 | 68 | fixed_point operator / (fixed_point r) const { fixed_point x = *this; x /= r; return x;} |
sravet | 0:aa2871c4c041 | 69 | |
sravet | 0:aa2871c4c041 | 70 | bool operator == (fixed_point r) const { return intValue == r.intValue; } |
sravet | 0:aa2871c4c041 | 71 | bool operator != (fixed_point r) const { return !(*this == r); } |
sravet | 0:aa2871c4c041 | 72 | bool operator < (fixed_point r) const { return intValue < r.intValue; } |
sravet | 0:aa2871c4c041 | 73 | bool operator > (fixed_point r) const { return intValue > r.intValue; } |
sravet | 0:aa2871c4c041 | 74 | bool operator <= (fixed_point r) const { return intValue <= r.intValue; } |
sravet | 0:aa2871c4c041 | 75 | bool operator >= (fixed_point r) const { return intValue >= r.intValue; } |
sravet | 0:aa2871c4c041 | 76 | |
sravet | 0:aa2871c4c041 | 77 | fixed_point operator + (int32_t r) const { fixed_point x = *this; x += r; return x;} |
sravet | 0:aa2871c4c041 | 78 | fixed_point operator - (int32_t r) const { fixed_point x = *this; x -= r; return x;} |
sravet | 0:aa2871c4c041 | 79 | fixed_point operator * (int32_t r) const { fixed_point x = *this; x *= r; return x;} |
sravet | 0:aa2871c4c041 | 80 | fixed_point operator / (int32_t r) const { fixed_point x = *this; x /= r; return x;} |
sravet | 0:aa2871c4c041 | 81 | operator int() const { return intValue>>p; } |
sravet | 0:aa2871c4c041 | 82 | operator float() const { return fix2float<p>(intValue); } |
sravet | 0:aa2871c4c041 | 83 | }; |
sravet | 0:aa2871c4c041 | 84 | |
sravet | 0:aa2871c4c041 | 85 | // Specializations for use with plain integers |
sravet | 0:aa2871c4c041 | 86 | template <int p> |
sravet | 0:aa2871c4c041 | 87 | inline fixed_point<p> operator + (int32_t a, fixed_point<p> b) |
sravet | 0:aa2871c4c041 | 88 | { return b + a; } |
sravet | 0:aa2871c4c041 | 89 | |
sravet | 0:aa2871c4c041 | 90 | template <int p> |
sravet | 0:aa2871c4c041 | 91 | inline fixed_point<p> operator - (int32_t a, fixed_point<p> b) |
sravet | 0:aa2871c4c041 | 92 | { return -b + a; } |
sravet | 0:aa2871c4c041 | 93 | |
sravet | 0:aa2871c4c041 | 94 | template <int p> |
sravet | 0:aa2871c4c041 | 95 | inline fixed_point<p> operator * (int32_t a, fixed_point<p> b) |
sravet | 0:aa2871c4c041 | 96 | { return b * a; } |
sravet | 0:aa2871c4c041 | 97 | |
sravet | 0:aa2871c4c041 | 98 | template <int p> |
sravet | 0:aa2871c4c041 | 99 | inline fixed_point<p> operator / (int32_t a, fixed_point<p> b) |
sravet | 0:aa2871c4c041 | 100 | { fixed_point<p> r(a); r /= b; return r; } |
sravet | 0:aa2871c4c041 | 101 | |
sravet | 0:aa2871c4c041 | 102 | // math functions |
sravet | 0:aa2871c4c041 | 103 | // no default implementation |
sravet | 0:aa2871c4c041 | 104 | |
sravet | 0:aa2871c4c041 | 105 | template <int p> |
sravet | 0:aa2871c4c041 | 106 | inline fixed_point<p> sin(fixed_point<p> a); |
sravet | 0:aa2871c4c041 | 107 | |
sravet | 0:aa2871c4c041 | 108 | template <int p> |
sravet | 0:aa2871c4c041 | 109 | inline fixed_point<p> cos(fixed_point<p> a); |
sravet | 0:aa2871c4c041 | 110 | |
sravet | 0:aa2871c4c041 | 111 | template <int p> |
sravet | 0:aa2871c4c041 | 112 | inline fixed_point<p> sqrt(fixed_point<p> a); |
sravet | 0:aa2871c4c041 | 113 | |
sravet | 0:aa2871c4c041 | 114 | template <int p> |
sravet | 0:aa2871c4c041 | 115 | inline fixed_point<p> rsqrt(fixed_point<p> a); |
sravet | 0:aa2871c4c041 | 116 | |
sravet | 0:aa2871c4c041 | 117 | template <int p> |
sravet | 0:aa2871c4c041 | 118 | inline fixed_point<p> inv(fixed_point<p> a); |
sravet | 0:aa2871c4c041 | 119 | |
sravet | 0:aa2871c4c041 | 120 | template <int p> |
sravet | 0:aa2871c4c041 | 121 | inline fixed_point<p> abs(fixed_point<p> a) |
sravet | 0:aa2871c4c041 | 122 | { |
sravet | 0:aa2871c4c041 | 123 | fixed_point<p> r; |
sravet | 0:aa2871c4c041 | 124 | r.intValue = a.intValue > 0 ? a.intValue : -a.intValue; |
sravet | 0:aa2871c4c041 | 125 | return r; |
sravet | 0:aa2871c4c041 | 126 | } |
sravet | 0:aa2871c4c041 | 127 | |
sravet | 0:aa2871c4c041 | 128 | // specializations for 16.16 format |
sravet | 0:aa2871c4c041 | 129 | |
sravet | 0:aa2871c4c041 | 130 | template <> |
sravet | 0:aa2871c4c041 | 131 | inline fixed_point<16> sin(fixed_point<16> a) |
sravet | 0:aa2871c4c041 | 132 | { |
sravet | 0:aa2871c4c041 | 133 | fixed_point<16> r; |
sravet | 0:aa2871c4c041 | 134 | r.intValue = fixsin16(a.intValue); |
sravet | 0:aa2871c4c041 | 135 | return r; |
sravet | 0:aa2871c4c041 | 136 | } |
sravet | 0:aa2871c4c041 | 137 | |
sravet | 0:aa2871c4c041 | 138 | template <> |
sravet | 0:aa2871c4c041 | 139 | inline fixed_point<16> cos(fixed_point<16> a) |
sravet | 0:aa2871c4c041 | 140 | { |
sravet | 0:aa2871c4c041 | 141 | fixed_point<16> r; |
sravet | 0:aa2871c4c041 | 142 | r.intValue = fixcos16(a.intValue); |
sravet | 0:aa2871c4c041 | 143 | return r; |
sravet | 0:aa2871c4c041 | 144 | } |
sravet | 0:aa2871c4c041 | 145 | |
sravet | 0:aa2871c4c041 | 146 | |
sravet | 0:aa2871c4c041 | 147 | template <> |
sravet | 0:aa2871c4c041 | 148 | inline fixed_point<16> sqrt(fixed_point<16> a) |
sravet | 0:aa2871c4c041 | 149 | { |
sravet | 0:aa2871c4c041 | 150 | fixed_point<16> r; |
sravet | 0:aa2871c4c041 | 151 | r.intValue = fixsqrt16(a.intValue); |
sravet | 0:aa2871c4c041 | 152 | return r; |
sravet | 0:aa2871c4c041 | 153 | } |
sravet | 0:aa2871c4c041 | 154 | |
sravet | 0:aa2871c4c041 | 155 | template <> |
sravet | 0:aa2871c4c041 | 156 | inline fixed_point<16> rsqrt(fixed_point<16> a) |
sravet | 0:aa2871c4c041 | 157 | { |
sravet | 0:aa2871c4c041 | 158 | fixed_point<16> r; |
sravet | 0:aa2871c4c041 | 159 | r.intValue = fixrsqrt16(a.intValue); |
sravet | 0:aa2871c4c041 | 160 | return r; |
sravet | 0:aa2871c4c041 | 161 | } |
sravet | 0:aa2871c4c041 | 162 | |
sravet | 0:aa2871c4c041 | 163 | template <> |
sravet | 0:aa2871c4c041 | 164 | inline fixed_point<16> inv(fixed_point<16> a) |
sravet | 0:aa2871c4c041 | 165 | { |
sravet | 0:aa2871c4c041 | 166 | fixed_point<16> r; |
sravet | 0:aa2871c4c041 | 167 | r.intValue = fixinv<16>(a.intValue); |
sravet | 0:aa2871c4c041 | 168 | return r; |
sravet | 0:aa2871c4c041 | 169 | } |
sravet | 0:aa2871c4c041 | 170 | |
sravet | 0:aa2871c4c041 | 171 | // The multiply accumulate case can be optimized. |
sravet | 0:aa2871c4c041 | 172 | template <int p> |
sravet | 0:aa2871c4c041 | 173 | inline fixed_point<p> multiply_accumulate( |
sravet | 0:aa2871c4c041 | 174 | int count, |
sravet | 0:aa2871c4c041 | 175 | const fixed_point<p> *a, |
sravet | 0:aa2871c4c041 | 176 | const fixed_point<p> *b) |
sravet | 0:aa2871c4c041 | 177 | { |
sravet | 0:aa2871c4c041 | 178 | long long result = 0; |
sravet | 0:aa2871c4c041 | 179 | for (int i = 0; i < count; ++i) |
sravet | 0:aa2871c4c041 | 180 | result += static_cast<long long>(a[i].intValue) * b[i].intValue; |
sravet | 0:aa2871c4c041 | 181 | fixed_point<p> r; |
sravet | 0:aa2871c4c041 | 182 | r.intValue = static_cast<int>(result >> p); |
sravet | 0:aa2871c4c041 | 183 | return r; |
sravet | 0:aa2871c4c041 | 184 | } |
sravet | 0:aa2871c4c041 | 185 | |
sravet | 0:aa2871c4c041 | 186 | } // end namespace fixedpoint |
sravet | 0:aa2871c4c041 | 187 | |
sravet | 0:aa2871c4c041 | 188 | #endif |
sravet | 0:aa2871c4c041 | 189 |