fixed.h 13 KB

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