CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

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