FIXED.H (13513B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/FIXED.H 1 3/03/97 10:24a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : FIXED.H * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 06/19/96 * 28 * * 29 * Last Update : June 19, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 34 35 36 #ifndef FIXED_H 37 #define FIXED_H 38 39 /* 40 ** The "bool" integral type was defined by the C++ committee in 41 ** November of '94. Until the compiler supports this, use the following 42 ** definition. 43 */ 44 #ifndef __BORLANDC__ 45 #ifndef TRUE_FALSE_DEFINED 46 #define TRUE_FALSE_DEFINED 47 enum {false=0,true=1}; 48 typedef int bool; 49 #endif 50 #endif 51 52 //#pragma warning 604 9 53 //#pragma warning 595 9 54 55 /* 56 ** This is a very simple fixed point class that functions like a regular integral type. However 57 ** it is under certain restrictions. The whole part must not exceed 65535. The fractional part is 58 ** limited to an accuracy of 1/65536. It cannot represent or properly handle negative values. It 59 ** really isn't all that fast (if an FPU is guaranteed to be present than using "float" might be 60 ** more efficient). It doesn't detect overflow or underflow in mathematical or bit-shift operations. 61 ** 62 ** Take careful note that the normal mathematical operators return integers and not fixed point 63 ** values if either of the components is an integer. This is the normal C auto-upcasting rule 64 ** as it would apply presuming that integers are considered to be of higher precision than 65 ** fixed point numbers. This allows the result of these operators to generate values with greater 66 ** magnitude than is normally possible if the result were coerced into a fixed point number. 67 ** If the result should be fixed point, then ensure that both parameters are fixed point. 68 ** 69 ** Note that although integers are used as the parameters in the mathematical operators, this 70 ** does not imply that negative parameters are supported. The use of integers is as a convenience 71 ** to the programmer -- constant integers are presumed signed. If unsigned parameters were 72 ** specified, then the compiler would have ambiguous conversion situation in the case of constant 73 ** integers (e.g. 1, 10, 32, etc). This is most important for the constructor when dealing with the 74 ** "0" parameter case. In that situation the compiler might interpret the "0" as a null pointer rather 75 ** than an unsigned integer. There should be no adverse consequences of using signed integer parameters 76 ** since the precision/magnitude of these integers far exceeds the fixed point component counterparts. 77 ** 78 ** Note that when integer values are returns from the arithmetic operators, the value is rounded 79 ** to the nearest whole integer value. This differs from normal integer math that always rounds down. 80 */ 81 class fixed 82 { 83 static constexpr unsigned int PRECISION = 1 << 16; 84 85 public: 86 // The default constructor must not touch the data members in any way. 87 fixed(void) {} 88 89 // Copy constructor 90 fixed(fixed const & rvalue) {Data.Raw = rvalue.Data.Raw;} 91 92 // Convenient constructor if numerator and denominator components are known. 93 fixed(int numerator, int denominator); 94 95 // Conversion constructor to get fixed point from integer. 96 fixed(int value) {Data.Composite.Fraction = 0U;Data.Composite.Whole = (unsigned short)value;} 97 fixed(unsigned int value) {Data.Composite.Fraction = 0U;Data.Composite.Whole = (unsigned short)value;} 98 99 // Conversion constructor to get fixed point from floating-point. 100 fixed(float value) {value += 1.0f/(PRECISION<<1);Data.Composite.Fraction = (unsigned short)((value - (unsigned short)value) * PRECISION);Data.Composite.Whole = (unsigned short)value;} 101 102 // Constructor if ASCII image of number is known. 103 fixed(char const * ascii); 104 105 // Convert to integer when implicitly required. 106 operator unsigned (void) const {return(unsigned)(((unsigned __int64)Data.Raw+(PRECISION>>1)) / PRECISION);} 107 108 /* 109 ** The standard operators as they apply to in-place operation. 110 */ 111 fixed & operator *= (fixed const & rvalue) {Data.Raw = (unsigned int)(((unsigned __int64)Data.Raw * rvalue.Data.Raw) / PRECISION);return(*this);} 112 fixed & operator *= (int rvalue) {Data.Raw *= (unsigned int)rvalue;return(*this);} 113 fixed & operator /= (fixed const & rvalue) {if (rvalue.Data.Raw != 0U && rvalue.Data.Raw != PRECISION) Data.Raw = (unsigned int)((((unsigned __int64)Data.Raw * PRECISION)+(PRECISION>>1)) / rvalue.Data.Raw);return(*this);} 114 fixed & operator /= (int rvalue) {if (rvalue) Data.Raw /= (unsigned int)rvalue;return(*this);} 115 fixed & operator += (fixed const & rvalue) {Data.Raw += rvalue.Data.Raw;return(*this);} 116 fixed & operator -= (fixed const & rvalue) {Data.Raw -= rvalue.Data.Raw;return(*this);} 117 118 /* 119 ** The standard "My Dear Aunt Sally" operators. The integer versions of multiply 120 ** and divide are more efficient than using the fixed point counterparts. 121 */ 122 const fixed operator * (fixed const & rvalue) const { return fixed(*this) *= rvalue; } 123 const int operator * (int rvalue) const { return fixed(*this) *= rvalue; } 124 const fixed operator / (fixed const & rvalue) const { return fixed(*this) /= rvalue; } 125 const int operator / (int rvalue) const { return fixed(*this) /= rvalue; } 126 const fixed operator + (fixed const & rvalue) const { return fixed(*this) += rvalue; } 127 const int operator + (int rvalue) const { return fixed(*this) += rvalue; } 128 const fixed operator - (fixed const & rvalue) const { return fixed(*this) -= rvalue; } 129 const int operator - (int rvalue) const { return fixed(*this) -= rvalue; } 130 131 /* 132 ** The Shift operators are more efficient than using multiplies or divides by power-of-2 numbers. 133 */ 134 fixed & operator >>= (unsigned rvalue) {Data.Raw >>= rvalue;return(*this);} 135 fixed & operator <<= (unsigned rvalue) {Data.Raw <<= rvalue;return(*this);} 136 const fixed operator >> (unsigned rvalue) const {return fixed(*this) >>= rvalue;} 137 const fixed operator << (unsigned rvalue) const {return fixed(*this) <<= rvalue;} 138 139 /* 140 ** The full set of comparison operators. 141 */ 142 bool operator == (fixed const & rvalue) const {return(Data.Raw == rvalue.Data.Raw);} 143 bool operator != (fixed const & rvalue) const {return(Data.Raw != rvalue.Data.Raw);} 144 bool operator < (fixed const & rvalue) const {return(Data.Raw < rvalue.Data.Raw);} 145 bool operator > (fixed const & rvalue) const {return(Data.Raw > rvalue.Data.Raw);} 146 bool operator <= (fixed const & rvalue) const {return(Data.Raw <= rvalue.Data.Raw);} 147 bool operator >= (fixed const & rvalue) const {return(Data.Raw >= rvalue.Data.Raw);} 148 bool operator ! (void) const {return(Data.Raw == 0U);} 149 150 /* 151 ** Comparison to integers requires consideration of fractional component. 152 */ 153 bool operator < (int rvalue) const {return(Data.Raw < ((unsigned int)rvalue*PRECISION));} 154 bool operator > (int rvalue) const {return(Data.Raw > ((unsigned int)rvalue*PRECISION));} 155 bool operator <= (int rvalue) const {return(Data.Raw <= ((unsigned int)rvalue*PRECISION));} 156 bool operator >= (int rvalue) const {return(Data.Raw >= ((unsigned int)rvalue*PRECISION));} 157 bool operator == (int rvalue) const {return(Data.Raw == ((unsigned int)rvalue*PRECISION));} 158 bool operator != (int rvalue) const {return(Data.Raw != ((unsigned int)rvalue*PRECISION));} 159 160 /* 161 ** Friend functions to handle the alternate positioning of fixed and integer parameters. 162 */ 163 friend const int operator * (int lvalue, fixed const & rvalue) { return fixed(lvalue) * rvalue; } 164 friend const int operator / (int lvalue, fixed const & rvalue) { return fixed(lvalue) / rvalue; } 165 friend const int operator + (int lvalue, fixed const & rvalue) { return fixed(lvalue) + rvalue; } 166 friend const int operator - (int lvalue, fixed const & rvalue) { return fixed(lvalue) - rvalue; } 167 friend bool operator < (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) < rvalue; } 168 friend bool operator > (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) > rvalue; } 169 friend bool operator <= (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) <= rvalue; } 170 friend bool operator >= (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) >= rvalue; } 171 friend bool operator == (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) == rvalue; } 172 friend bool operator != (unsigned lvalue, fixed const & rvalue) { return fixed(lvalue) != rvalue; } 173 friend int operator *= (int & lvalue, fixed const & rvalue) { lvalue = lvalue * rvalue; return(lvalue); } 174 friend int operator /= (int & lvalue, fixed const & rvalue) { lvalue = lvalue / rvalue; return(lvalue); } 175 friend int operator += (int & lvalue, fixed const & rvalue) { lvalue = lvalue + rvalue; return(lvalue); } 176 friend int operator -= (int & lvalue, fixed const & rvalue) { lvalue = lvalue - rvalue; return(lvalue); } 177 178 /* 179 ** Helper functions to handle simple and common operations on fixed point numbers. 180 */ 181 void Round_Up(void) {Data.Raw += (PRECISION-1U);Data.Composite.Fraction = 0U;} 182 void Round_Down(void) {Data.Composite.Fraction = 0U;} 183 void Round(void) {if (Data.Composite.Fraction >= PRECISION>>1) Round_Up();Round_Down();} 184 void Saturate(unsigned capvalue) {if (Data.Raw > (capvalue*PRECISION)) Data.Raw = capvalue*PRECISION;} 185 void Saturate(fixed const & capvalue) {if (*this > capvalue) *this = capvalue;} 186 void Sub_Saturate(unsigned capvalue) {if (Data.Raw >= (capvalue*PRECISION)) Data.Raw = (capvalue*PRECISION)-1U;} 187 void Sub_Saturate(fixed const & capvalue) {if (*this >= capvalue) Data.Raw = capvalue.Data.Raw-1U;} 188 void Inverse(void) {*this = fixed(1) / *this;} 189 190 /* 191 ** Friend helper functions that work in the typical C fashion of passing the object to 192 ** be processed as a parameter to the function. 193 */ 194 friend const fixed Round_Up(fixed const & value) {fixed temp = value; temp.Round_Up();return(temp);} 195 friend const fixed Round_Down(fixed const & value) {fixed temp = value; temp.Round_Down();return(temp);} 196 friend const fixed Round(fixed const & value) {fixed temp = value; temp.Round();return(temp);} 197 friend const fixed Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);} 198 friend const fixed Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Saturate(capvalue);return(temp);} 199 friend const fixed Sub_Saturate(fixed const & value, unsigned capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);} 200 friend const fixed Sub_Saturate(fixed const & value, fixed const & capvalue) {fixed temp = value;temp.Sub_Saturate(capvalue);return(temp);} 201 friend const fixed Inverse(fixed const & value) {fixed temp = value;temp.Inverse();return(temp);} 202 203 /* 204 ** Conversion of the fixed point number into an ASCII string. 205 */ 206 int To_ASCII(char * buffer, int maxlen=-1) const; 207 char const * As_ASCII(void) const; 208 209 /* 210 ** Helper constants that provide some convenient fixed point values. 211 */ 212 static const fixed _1_2; 213 static const fixed _1_3; 214 static const fixed _1_4; 215 static const fixed _3_4; 216 static const fixed _2_3; 217 218 private: 219 union { 220 struct { 221 #ifdef BIG_ENDIAN 222 unsigned short Whole; 223 unsigned short Fraction; 224 #else 225 unsigned short Fraction; 226 unsigned short Whole; 227 #endif 228 } Composite; 229 unsigned int Raw; 230 } Data; 231 }; 232 233 234 #endif