FixedPoint.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. #ifndef FIXED_POINT_H
  19. #define FIXED_POINT_H
  20. //====================
  21. #include "System.h" // for environment variables...
  22. #include "QuickMath.h"
  23. //====================
  24. /*****************************************************************
  25. This header depends on the rest QuickMath, but is not necessary
  26. for use of Quickmath, and deals primarily with high speed fixed
  27. point operations.
  28. /*****************************************************************
  29. Hungarian: fp = either generic fixed point or signed 32 (S16.U16)
  30. pfp = pointer to fixed point number
  31. (sorry FILE*)
  32. fpS32 = S16.U16
  33. type = RFixedS32, members = "frac" and "mod"
  34. fpS16 = S8.U8
  35. fpU16 = U8.U8, etc.
  36. type = RFixedS16, same members, etc., etc.
  37. & = implicit pass by reference, do NOT use a pointer
  38. & is used in almost all cases to prevent VC from creating
  39. a local stack frame which would slow things down by 20 times.
  40. NOTE: Some functions can take a long AS an fpS32. Understand that this is
  41. a memory cast as a fpS32 and does NOT represent the actual long "value"!
  42. Use Get and Set "Value" functions to translate integers to fixed point!
  43. /*****************************************************************
  44. RFixedS32 { mod, frac, copy }
  45. RFixedU16 { mod, frac, copy }
  46. inline RFixedS32 rspfpSin(sDeg)
  47. inline RFixedS32 rspfpCos(sDeg)
  48. inline RFixedS32 rspfpOneOver(sDen)
  49. inline void rspfpSet(&fpX,lVal) // lVal is an fpS32 in long form (mem)
  50. inline void rspfpAdd(f&pDst,&fpAdd)
  51. inline void rspfpSub(&fpDst,&fpSub)
  52. inline void rspfpMul(&fpDst,&fpMul)
  53. inline void rspfpMul(&fpDst,&fpA,&fpB)
  54. inline void rspfpMul(&fpDst,long lA,long lB) // fpS32 s as longs (mem)
  55. inline void rspfpAddHalf(&fpDst) // useful for rounding functions
  56. inline void rspfpSetValue(&fpDst,double dVal) // translates VALUE into fp
  57. inline double rspfpGetValue(&fpDst)
  58. /****************************************************************/
  59. // Fixed Point 32S
  60. //======================================= signed 15:16 fixed point
  61. typedef union {
  62. long val; //********* Full 32 bit signed value
  63. struct
  64. {
  65. #ifdef SYS_ENDIAN_BIG // big endian
  66. //-----------------------------------------------
  67. union
  68. {
  69. short mod; //********* signed 16-bit integer part
  70. struct {
  71. signed char upper; // for 256v level z-coloring:
  72. unsigned char lower;
  73. };
  74. };
  75. unsigned short frac; // unsigned 16-bit fractional part
  76. //-----------------------------------------------
  77. #else // little endian
  78. unsigned short frac;
  79. union // for 256v level z-coloring:
  80. {
  81. short mod;
  82. struct {
  83. unsigned char lower;
  84. signed char upper;
  85. };
  86. };
  87. #endif
  88. };
  89. } RFixedS32;
  90. //====================
  91. inline void rspfpSet(RFixedS32& s32fx,long lVal)
  92. { s32fx.val = lVal; }
  93. inline void rspfpAdd(RFixedS32& s32fx,RFixedS32& s32fxAdd)
  94. { s32fx.val += s32fxAdd.val; }
  95. inline void rspfpSub(RFixedS32& s32fx,RFixedS32& s32fxSub)
  96. { s32fx.val -= s32fxSub.val; }
  97. // NEED 64-bit multiplication to handle overflow!
  98. #if 0
  99. #ifdef _M_IX86 // INTEL!
  100. inline void rspfpMul(RFixedS32& s32fx,RFixedS32& s32fxMul)
  101. {
  102. // Use the 64-bit resultant to get the true value!
  103. __asm
  104. {
  105. mov eax,s32fx.val
  106. mov ebx,s32fxMul.val
  107. imul eax,ebx // result is in EDX::EAX
  108. mov s32fx.val,edx // only the upper word is valid!
  109. }
  110. }
  111. inline void rspfpMul(RFixedS32& s32fxC,RFixedS32& s32fxA,RFixedS32& s32fxB)
  112. {
  113. // Use the 64-bit resultant to get the true value!
  114. __asm
  115. {
  116. mov eax,s32fxA.val
  117. mov ebx,s32fxB.val
  118. imul ebx // ([*eax]) result is in EDX::EAX
  119. mov s32fxC.val,edx // only the upper word is valid!
  120. }
  121. }
  122. inline void rspfpMul(RFixedS32 &lC,long lA,long lB)
  123. {
  124. union {
  125. unsigned long val;
  126. struct { unsigned short lo; unsigned short hi; };
  127. } temp;
  128. long temp2;
  129. // Use the 64-bit resultant to get the true value!
  130. __asm
  131. {
  132. mov eax,lA
  133. mov ebx,lB
  134. imul ebx // ([*eax]) result is in EDX::EAX
  135. // PROBLEM: we want bits 16-47!!!!!!
  136. mov temp2,edx // only need hwlf the integral part...
  137. mov temp,eax // get upper half!
  138. }
  139. lC.mod = (short)temp2; // keep sign, lose upper half!
  140. lC.frac = temp.hi;
  141. }
  142. #endif
  143. #endif
  144. inline void rspfpAddHalf(RFixedS32& s32fx) // useful for rounding
  145. { s32fx.val += (long)32768; }
  146. //========================= debugging only! (slow)
  147. inline void rspfpSetValue(RFixedS32& s32fx,double dVal)
  148. { s32fx.val = (long) (dVal * 65536.0); }
  149. inline double rspfpGetValue(RFixedS32& s32fx)
  150. { return (double)s32fx.mod + (double)s32fx.frac / (double)65536.0; }
  151. // For passing back an error:
  152. const RFixedS32 s32fxERROR = {-65536};
  153. // For fixed32 type stuff:
  154. //extern unsigned long OneOver[256];
  155. //extern void SetOneOver();
  156. #define NUM_ONEOVER_FP32 1280
  157. class RInitNum
  158. {
  159. public:
  160. RInitNum();
  161. static long OneOver[NUM_ONEOVER_FP32];
  162. };
  163. //======================================= unsigned 8:8 fixed point
  164. typedef union {
  165. unsigned short val;
  166. struct
  167. {
  168. #ifdef SYS_ENDIAN_BIG // big endian
  169. unsigned char mod;
  170. unsigned char frac;
  171. #else // little endian
  172. unsigned char frac;
  173. unsigned char mod;
  174. #endif
  175. };
  176. } RFixedU16;
  177. //-------------------------------------
  178. //======================================= signed 8:8 fixed point
  179. typedef union {
  180. signed short val;
  181. struct
  182. {
  183. #ifdef SYS_ENDIAN_BIG // big endian
  184. signed char mod;
  185. unsigned char frac;
  186. #else // little endian
  187. unsigned char frac;
  188. signed char mod;
  189. #endif
  190. };
  191. } RFixedS16;
  192. //-------------------------------------
  193. //====================
  194. extern RFixedS32 fpSINQ[csNumRotSteps],fpCOSQ[csNumRotSteps];
  195. extern void InitTrigFP();
  196. inline RFixedS32 rspfpSin(short sDeg) { return fpSINQ[sDeg]; }
  197. inline RFixedS32 rspfpCos(short sDeg) { return fpCOSQ[sDeg]; }
  198. inline long rspfpOneOver(short sDen) { return RInitNum::OneOver[sDen]; }
  199. // Auto Initialize hook!
  200. class RQuickTrigFP
  201. {
  202. public:
  203. RQuickTrigFP() { InitTrigFP(); TRACE("QTRIG fixed point initialized!\n"); }
  204. ~RQuickTrigFP() { }
  205. };
  206. //====================
  207. #endif