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, and added the functionality to cast between precisions.

Committer:
madcowswe
Date:
Sun Nov 27 05:10:45 2011 +0000
Revision:
1:ac99b6f474a0
Parent:
0:ca79fb4a8165
Made it possible to cast to double

Who changed what in which revision?

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