FIXED.H 13 KB

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