| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
- <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
- <title>EAFixedPoint</title>
- <meta name="author" content="Paul Pedriana">
- <link type="text/css" rel="stylesheet" href="UTFDoc.css">
- </head>
- <body bgcolor="#FFFFFF">
- <h1>EAFixedPoint</h1>
- <h2> <span style="font-weight: bold;">Introduction</span> </h2>
- <p>The EAFixedPoint module implements fixed point math via classic C macros and
- functions and via a more advanced implementation using C++ classes. The C++
- classes constitute a fairly complete implementation of a fixed point C++ numerical
- data type that acts much like the built-in float and double data types. </p>
- <p>The following code freely mixes the SFixed16 (signed 16:16 fixed point) data
- type with other numerical data types:</p>
- <pre><span style="font-family: monospace;"><span class="code-example">SFixed16_16 a(1), b(2), c(3);<br>float f(4.5f);<br>double d(3.2);<br>int i(6);
- <br>a = b * f;<br>a = (c / d) + b + f;<br>a = c / d * (b % i) + f / c;<br>a = i * -c / (b++);<br>a = sin(a) + pow(b, d) * sqrt(a);<br>a = log(a) / log(f);</span></span></pre>
- <p></p>
- <p>Fixed point math has a number of uses:</p>
- <ul>
- <li>Improved precision over floating point math.</li>
- <li>Improved speed over floating point math, particularly with respect to division.</li>
- <li>Consistent behaviour across CPUs, especially during network play when two
- different machines must behave identically but FPU behaviour may differ.</li>
- </ul>
- <p>Information about fixed point can be found on the Internet by simply searching
- for "fixed point" with your favorite search site.</p>
- <h2>Fixed point vs. floating point </h2>
- <p>Fixed point</p>
- <blockquote>
- <p>+ Can be very fast. Fixed point
- math executes at the same speed as integer math. Fixed to int conversions
- are much faster float to int.<br>
- + Executes concurrently with floating point math, due its use of integer math.<br>
- – Limited range. Fixed point16:16 numbers are between -32767 and +32767.
- The fractional part is accurate to 1 / 65536. <br>
- – Harder to code in high-level languages.</p>
- </blockquote>
- <p>Floating point</p>
- <blockquote>
- <p>+ Large range. The range for floating point numbers is typically in excess
- of 1e-100 to 1e+100 and have an accuracy of about 13 decimal places. <br>
- + Executes concurrently with integer math.<br>
- – Can be slower. Generally
- fast for addition and multiplication but may be slower for division and float
- to int conversions. </p>
- </blockquote>
- <h2>Fixed point precision </h2>
- <p>The C++ fixed point classes provide varying precision via the use of template
- parameter constants. EAFixedPoint provides the following predefined C++ fixed
- point types</p>
- <table width="100%" border="1">
- <tr>
- <td><b>Type</b></td>
- <td><b>Signed</b></td>
- <td><b>Integral type</b></td>
- <td><b>Precision</b></td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed24_8</font></td>
- <td>signed</td>
- <td>32</td>
- <td>24 bits of integer, 8 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed24_8</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>24 bits of integer, 8 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed22_10</font></td>
- <td>signed</td>
- <td>32</td>
- <td>22 bits of integer, 10 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed22_10</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>22 bits of integer, 10 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed20_12</font></td>
- <td>signed</td>
- <td>32</td>
- <td>20 bits of integer, 12 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed20_12</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>20 bits of integer, 12 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed18_14</font></td>
- <td>signed</td>
- <td>32</td>
- <td>18 bits of integer, 14 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed18_14</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>18 bits of integer, 14 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed16_16</font></td>
- <td>signed</td>
- <td>32</td>
- <td>16 bits of integer, 16 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed16_16</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>16 bits of integer, 16 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed14_18</font></td>
- <td>signed</td>
- <td>32</td>
- <td>14 bits of integer, 18 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed14_18</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>14 bits of integer, 18 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed12_20</font></td>
- <td>signed</td>
- <td>32</td>
- <td>12 bits of integer, 20 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed12_20</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>12 bits of integer, 20 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed10_22</font></td>
- <td>signed</td>
- <td>32</td>
- <td>10 bits of integer, 22 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed10_22</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>10 bits of integer, 22 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed8_24</font></td>
- <td>signed</td>
- <td>32</td>
- <td>8 bits of integer, 24 bits of fraction</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed8_24</font></td>
- <td>unsigned</td>
- <td>32</td>
- <td>8 bits of integer, 24 bits of fraction</td>
- </tr>
- <tr>
- <td> </td>
- <td> </td>
- <td> </td>
- <td> </td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed48_16</font></td>
- <td>signed</td>
- <td>64</td>
- <td>48 bits of integer, 16 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed48_16</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>48 bits of integer, 16 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed44_20</font></td>
- <td>signed</td>
- <td>64</td>
- <td>44 bits of integer, 20 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed44_20</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>44 bits of integer, 20 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed40_24</font></td>
- <td>signed</td>
- <td>64</td>
- <td>40 bits of integer, 24 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed40_24</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>40 bits of integer, 24 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed36_28</font></td>
- <td>signed</td>
- <td>64</td>
- <td>36 bits of integer, 28 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed36_28</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>36 bits of integer, 28 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed32_32</font></td>
- <td>signed</td>
- <td>64</td>
- <td>32 bits of integer, 32 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed32_32</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>32 bits of integer, 32 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed28_36</font></td>
- <td>signed</td>
- <td>64</td>
- <td>28 bits of integer, 36 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed28_36</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>28 bits of integer, 36 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed24_40</font></td>
- <td>signed</td>
- <td>64</td>
- <td>24 bits of integer, 40 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed24_40</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>24 bits of integer, 40 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed20_44</font></td>
- <td>signed</td>
- <td>64</td>
- <td>20 bits of integer, 44 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed20_44</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>20 bits of integer, 44 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">SFixed16_48</font></td>
- <td>signed</td>
- <td>64</td>
- <td>16 bits of integer, 48 bits of fraction.</td>
- </tr>
- <tr>
- <td><font face="Courier New, Courier, mono" size="-1">UFixed16_48</font></td>
- <td>unsigned</td>
- <td>64</td>
- <td>16 bits of integer, 48 bits of fraction.</td>
- </tr>
- </table>
- <h2>Example usage </h2>
- <p>To a large degree, you can use fixed point types the same way you would use
- floating point types. </p>
- <p>Mixed integer math expressions (same as shown earlier above):</p>
- <pre class="code-example">SFixed16_16 a(1), b(2), c(3);<br>float f(4.5f);<br>double d(3.2);<br>int i(6);
- <br>a = b * f;<br>a = (c / d) + b + f;<br>a = c / d * (b % i) + f / c;<br>a = i * -c / (b++);<br>a = sin(a) + pow(b, d) * sqrt(a);<br>a = log(a) / log(f);</pre>
- <p>printf:</p>
- <pre class="code-example">SFixed24_8 f = 23.5f;<br><br>printf("%f", f.AsFloat());</pre>
- <p>Logical expresions:</p>
- <pre class="code-example">SFixed16_16 a = 20.4;
- SFixed16_16 b = 130.6;
- SFixed16_16 c = 223.3;
- if((a < b) || (b >= c) || (a < 23.5))
- a *= 25;</pre>
- <h2>Limitations </h2>
- <p>The primary differences between our fixed point type and a hypothetical built-in
- version are:</p>
- <ul>
- <li>EAFixedPoint doesn't implement cast operators. Instead, provides explicit
- converters such as AsInt, AsFloat, etc. This is by design, as such casting
- operators result in ambiguous conversions and would need built-in compiler
- knowledge to resolve the situation.</li>
- <li>Standard library functions such as sprintf have no support for such fixed
- point types. However, most of the time it is sufficient to convert to floating
- point and use the built-in floating point formatting functions.</li>
- <li>There is no explicit support for mixing expressions between two different
- fixed point types, such as SFixed16_16 with SFixed24_8. You can use these
- together via conversion between built-in types. </li>
- </ul>
- <h2>Interface </h2>
- <p>C interface:</p>
- <pre class="code-example">typedef int32_t EAFixed16;
-
- #define EAMAX_FIXED16 0x7fffffff
- #define EAMIN_FIXED16 0x80000000
- #define EAFixed16ToInt(a) ((int32_t)(a) >> 16)
- #define EAIntToFixed16(a) ((EAFixed16)((a) << 16))
- #define EAFixed16ToDouble(a) (((double)a) / 65536.0)
- #define EADoubleToFixed16(a) ((EAFixed16)((a) * 65536.0))
- #define EAFixed16ToFloat(a) (((float)a) / 65536.f)
- #define EAFloatToFixed16(a) ((EAFixed16)((a) * 65536.f))
- #define EAFixed16Negate(a) (-a)
- EAFixed16 EAFixed16Mul (EAFixed16 a, EAFixed16 b);
- EAFixed16 EAFixed16Div (EAFixed16 a, EAFixed16 b);
- EAFixed16 EAFixed16DivSafe (EAFixed16 a, EAFixed16 b);
- EAFixed16 EAFixed16MulDiv (EAFixed16 a, EAFixed16 b, EAFixed16 c);
- EAFixed16 EAFixed16MulDivSafe (EAFixed16 a, EAFixed16 b, EAFixed16 c);
- EAFixed16 EAFixed16Mod (EAFixed16 a, EAFixed16 b);
- EAFixed16 EAFixed16ModSafe (EAFixed16 a, EAFixed16 b);
- EAFixed16 EAFixed16Abs (EAFixed16 a);
- </pre>
- <p>C++ interface, by example of SFixed16_16. Note that nearly all the functions
- below are implemented as simple inlines:</p>
- <pre class="code-example">struct SFixed16_16
- {
- SFixed16_16();
- SFixed16_16(const SFixed16_16& value);
- SFixed16_16(const int& value);
- SFixed16_16(const unsigned int& value);
- SFixed16_16(const long& value);
- SFixed16_16(const unsigned long& value);
- SFixed16_16(const float& value);
- SFixed16_16(const double& value);
- void FromFixed(const int& value);
- int32_t AsFixed();
- int AsInt() const;
- unsigned int AsUnsignedInt() const;
- long AsLong() const;
- unsigned long AsUnsignedLong()const;
- float AsFloat() const;
- double AsDouble() const;
- SFixed16_16& operator=(const SFixed16_16& value);
- SFixed16_16& operator=(const int& value);
- SFixed16_16& operator=(const unsigned int& value);
- SFixed16_16& operator=(const long& value);
- SFixed16_16& operator=(const unsigned long& value);
- SFixed16_16& operator=(const float& value);
- SFixed16_16& operator=(const double& value);
- bool operator< (const SFixed16_16& value) const;
- bool operator> (const SFixed16_16& value) const;
- bool operator>=(const SFixed16_16& value) const;
- bool operator<=(const SFixed16_16& value) const;
- bool operator==(const SFixed16_16& value) const;
- bool operator!=(const SFixed16_16& value) const;
-
- bool operator< (const int& value) const;
- bool operator> (const int& value) const;
- bool operator>=(const int& value) const;
- bool operator<=(const int& value) const;
- bool operator==(const int& value) const;
- bool operator!=(const int& value) const;
-
- bool operator< (const unsigned int& value) const;
- bool operator> (const unsigned int& value) const;
- bool operator>=(const unsigned int& value) const;
- bool operator<=(const unsigned int& value) const;
- bool operator==(const unsigned int& value) const;
- bool operator!=(const unsigned int& value) const;
-
- bool operator< (const long& value) const;
- bool operator> (const long& value) const;
- bool operator>=(const long& value) const;
- bool operator<=(const long& value) const;
- bool operator==(const long& value) const;
- bool operator!=(const long& value) const;
-
- bool operator< (const unsigned long& value) const;
- bool operator> (const unsigned long& value) const;
- bool operator>=(const unsigned long& value) const;
- bool operator<=(const unsigned long& value) const;
- bool operator==(const unsigned long& value) const;
- bool operator!=(const unsigned long& value) const;
- bool operator< (const float& value) const;
- bool operator> (const float& value) const;
- bool operator>=(const float& value) const;
- bool operator<=(const float& value) const;
- bool operator==(const float& value) const;
- bool operator!=(const float& value) const;
-
- bool operator< (const double& value) const;
- bool operator> (const double& value) const;
- bool operator>=(const double& value) const;
- bool operator<=(const double& value) const;
- bool operator==(const double& value) const;
- bool operator!=(const double& value) const;
- bool operator! () const;
-
- SFixed16_16 operator~() const;
- SFixed16_16 operator-() const;
- SFixed16_16 operator+() const;
- SFixed16_16& operator+=(const SFixed16_16& value);
- SFixed16_16& operator+=(const int& value);
- SFixed16_16& operator+=(const unsigned int& value);
- SFixed16_16& operator+=(const long & value);
- SFixed16_16& operator+=(const unsigned long& value);
- SFixed16_16& operator+=(const float& value);
- SFixed16_16& operator+=(const double& value);
- SFixed16_16& operator-=(const SFixed16_16& value);
- SFixed16_16& operator-=(const int& value);
- SFixed16_16& operator-=(const unsigned int& value);
- SFixed16_16& operator-=(const long& value);
- SFixed16_16& operator-=(const unsigned long& value);
- SFixed16_16& operator-=(const float& value);
- SFixed16_16& operator-=(const double& value);
- SFixed16_16& operator*=(const SFixed16_16& value);
- SFixed16_16& operator*=(const int& value)
- SFixed16_16& operator*=(const unsigned int& value)
- SFixed16_16& operator*=(const long& value)
- SFixed16_16& operator*=(const unsigned long& value);
- SFixed16_16& operator*=(const float& value);
- SFixed16_16& operator*=(const double& value);
- SFixed16_16& operator/=(const SFixed16_16& value);
- SFixed16_16& operator/=(const int& value);
- SFixed16_16& operator/=(const unsigned int& value);
- SFixed16_16& operator/=(const long& value);
- SFixed16_16& operator/=(const unsigned long& value);
- SFixed16_16& operator/=(const float& value);
- SFixed16_16& operator/=(const double& value);
- SFixed16_16& operator%=(const SFixed16_16& value);
- SFixed16_16& operator%=(const int& value);
- SFixed16_16& operator%=(const unsigned int& value);
- SFixed16_16& operator%=(const long& value);
- SFixed16_16& operator%=(const unsigned long& value);
- SFixed16_16& operator%=(const float& value);
- SFixed16_16& operator%=(const double& value);
- SFixed16_16& operator|=(const SFixed16_16& value);
- SFixed16_16& operator|=(const int& value);
- SFixed16_16& operator&=(const SFixed16_16& value);
- SFixed16_16& operator&=(const int& value);
- SFixed16_16& operator^=(const SFixed16_16& value);
- SFixed16_16& operator^=(const int& value);
- SFixed16_16 operator<<(int numBits) const;
- SFixed16_16 operator>>(int numBits) const;
- SFixed16_16& operator<<=(int numBits);
- SFixed16_16& operator>>=(int numBits);
- SFixed16_16& operator++();
- SFixed16_16& operator--();
- SFixed16_16 operator++(int);
- SFixed16_16 operator--(int);
- SFixed16_16 Abs();
- SFixed16_16 DivSafe(const SFixed16_16& denominator);
- SFixed16_16& DivSafeAssign(const SFixed16_16& denominator);
- }<font color="#000099">;</font>
- </pre>
- <hr>
- <p><br>
- <br>
- <br>
- <span style="font-family: monospace;"> </span><br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- </p>
- </body></html>
|