/opengles/src/fixed.cpp

http://ftk.googlecode.com/ · C++ · 268 lines · 142 code · 29 blank · 97 comment · 36 complexity · c137a20b9b46ff5205c43dbeae50efb9 MD5 · raw file

  1. // ==========================================================================
  2. //
  3. // fixed.cpp Implementation of Fixed Point Arithmetic
  4. //
  5. // If Intel Graphics Performance Primitives (GPP) are available,
  6. // the functions defined in this header should be mapped to
  7. // the assembler primitives provided in this library.
  8. //
  9. // Fixed point numbers are represented in 16.16 format, where
  10. // the high 16 bits represent the signed integer part, while the
  11. // lower 16 bits represent the fractional part of a number.
  12. //
  13. // --------------------------------------------------------------------------
  14. //
  15. // Copyright (C) 2003 David Blythe All Rights Reserved.
  16. //
  17. // Permission is hereby granted, free of charge, to any person obtaining a
  18. // copy of this software and associated documentation files (the "Software"),
  19. // to deal in the Software without restriction, including without limitation
  20. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  21. // and/or sell copies of the Software, and to permit persons to whom the
  22. // Software is furnished to do so, subject to the following conditions:
  23. //
  24. // The above copyright notice and this permission notice shall be included
  25. // in all copies or substantial portions of the Software.
  26. //
  27. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  28. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  30. // DAVID BLYTHE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  31. // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  32. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. //
  34. // ==========================================================================
  35. #include "stdafx.h"
  36. #include "fixed.h"
  37. #ifndef EGL_USE_GPP
  38. // --------------------------------------------------------------------------
  39. // Calculate inverse of fixed point number
  40. //
  41. // Parameters:
  42. // a - the number whose inverse should be calculated
  43. // --------------------------------------------------------------------------
  44. EGL_Fixed EGL_Inverse(EGL_Fixed a) {
  45. I32 exp;
  46. EGL_Fixed x;
  47. /* 1/(4x) */
  48. static const I32 __gl_rcp_tab[] = { /* domain 0.5 .. 1.0-1/16 */
  49. 0x8000, 0x71c7, 0x6666, 0x5d17, 0x5555, 0x4ec4, 0x4924, 0x4444
  50. };
  51. if (a == EGL_ZERO) return 0x7fffffff;
  52. bool sign = false;
  53. if (a < 0) {
  54. sign = true;
  55. a = -a;
  56. }
  57. #ifdef EGL_USE_CLZ
  58. exp = _CountLeadingZeros(a);
  59. #else
  60. x = a;
  61. exp = 31;
  62. if (x & 0xffff0000) { exp -= 16; x >>= 16; }
  63. if (x & 0xff00) { exp -= 8; x >>= 8; }
  64. if (x & 0xf0) { exp -= 4; x >>= 4; }
  65. if (x & 0xc) { exp -= 2; x >>= 2; }
  66. if (x & 0x2) { exp -= 1; }
  67. #endif
  68. x = __gl_rcp_tab[(a>>(28-exp))&0x7]<<2;
  69. exp -= 16;
  70. if (exp <= 0)
  71. x >>= -exp;
  72. else
  73. x <<= exp;
  74. //printf("est %f\n", __GL_F_2_FLOAT(x));
  75. /* two iterations of newton-raphson x = x(2-ax) */
  76. x = EGL_Mul(x,(EGL_ONE*2 - EGL_Mul(a,x)));
  77. x = EGL_Mul(x,(EGL_ONE*2 - EGL_Mul(a,x)));
  78. //printf("recip %f %f\n", __GL_F_2_FLOAT(a), __GL_F_2_FLOAT(x));
  79. if (sign)
  80. return -x;
  81. else
  82. return x;
  83. }
  84. // --------------------------------------------------------------------------
  85. // Calculate the inverse of the square root of fixed point number
  86. //
  87. // Parameters:
  88. // a - the numbers whose inverse of square root should be
  89. // calculated
  90. // --------------------------------------------------------------------------
  91. EGL_Fixed EGL_InvSqrt(EGL_Fixed a) {
  92. EGL_Fixed x /*= (a+EGL_ONE)>>1*//*a>>1*/;
  93. /* 1/(2sqrt(x)) - extra divide by 2 to scale to 16 bits */
  94. static const U16 __gl_rsq_tab[] = { /* domain 0.5 .. 1.0-1/16 */
  95. 0xb504, 0xaaaa, 0xa1e8, 0x9a5f, 0x93cd, 0x8e00, 0x88d6, 0x8432,
  96. };
  97. I32 i, exp;
  98. if (a == EGL_ZERO) return 0x7fffffff;
  99. if (a == EGL_ONE) return a;
  100. #ifdef EGL_USE_CLZ
  101. exp = _CountLeadingZeros(a);
  102. #else
  103. x = a;
  104. exp = 31;
  105. if (x & 0xffff0000) { exp -= 16; x >>= 16; }
  106. if (x & 0xff00) { exp -= 8; x >>= 8; }
  107. if (x & 0xf0) { exp -= 4; x >>= 4; }
  108. if (x & 0xc) { exp -= 2; x >>= 2; }
  109. if (x & 0x2) { exp -= 1; }
  110. #endif
  111. x = __gl_rsq_tab[(a>>(28-exp))&0x7]<<1;
  112. //printf("t %f %x %f %d %d\n", __GL_F_2_FLOAT(a), a, __GL_F_2_FLOAT(x), exp, 28-exp);
  113. exp -= 16;
  114. if (exp <= 0)
  115. x >>= -exp>>1;
  116. else
  117. x <<= (exp>>1)+(exp&1);
  118. if (exp&1) x = EGL_Mul(x, __gl_rsq_tab[0]);
  119. //printf("nx %f\n", __GL_F_2_FLOAT(x));
  120. /* newton-raphson */
  121. /* x = x/2*(3-(a*x)*x) */
  122. i = 0;
  123. do {
  124. //printf("%f\n", __GL_F_2_FLOAT(x));
  125. x = EGL_Mul((x>>1),(EGL_ONE*3 - EGL_Mul(EGL_Mul(a,x),x)));
  126. } while(++i < 3);
  127. //printf("rsqrt %f %f\n", __GL_F_2_FLOAT(a), __GL_F_2_FLOAT(x));
  128. return x;
  129. }
  130. static const U16 __gl_sin_tab[] = {
  131. #include "gl_sin.h"
  132. };
  133. // --------------------------------------------------------------------------
  134. // Calculate cosine of fixed point number
  135. //
  136. // Parameters:
  137. // a - the numbers whose cosine should be calculated
  138. // --------------------------------------------------------------------------
  139. EGL_Fixed EGL_Cos(EGL_Fixed a) {
  140. EGL_Fixed v;
  141. /* reduce to [0,1) */
  142. while (a < EGL_ZERO) a += EGL_2PI;
  143. a *= EGL_R2PI;
  144. a >>= EGL_PRECISION;
  145. a += 0x4000;
  146. /* now in the range [0, 0xffff], reduce to [0, 0xfff] */
  147. a >>= 4;
  148. v = (a & 0x400) ? __gl_sin_tab[0x3ff - (a & 0x3ff)] : __gl_sin_tab[a & 0x3ff];
  149. v = EGL_Mul(v,EGL_ONE);
  150. return (a & 0x800) ? -v : v;
  151. }
  152. // --------------------------------------------------------------------------
  153. // Calculate sine of fixed point number
  154. //
  155. // Parameters:
  156. // value - the numbers whose sine should be calculated
  157. // --------------------------------------------------------------------------
  158. EGL_Fixed EGL_Sin(EGL_Fixed a) {
  159. EGL_Fixed v;
  160. /* reduce to [0,1) */
  161. while (a < EGL_ZERO) a += EGL_2PI;
  162. a *= EGL_R2PI;
  163. a >>= EGL_PRECISION;
  164. /* now in the range [0, 0xffff], reduce to [0, 0xfff] */
  165. a >>= 4;
  166. v = (a & 0x400) ? __gl_sin_tab[0x3ff - (a & 0x3ff)] : __gl_sin_tab[a & 0x3ff];
  167. v = EGL_Mul(v,EGL_ONE);
  168. return (a & 0x800) ? -v : v;
  169. }
  170. // --------------------------------------------------------------------------
  171. // Calculate square root of fixed point number
  172. //
  173. // Parameters:
  174. // value - the number whose square root should be calculated
  175. // --------------------------------------------------------------------------
  176. EGL_Fixed EGL_Sqrt(EGL_Fixed a) {
  177. EGL_Fixed s;
  178. I32 i;
  179. s = (a + EGL_ONE) >> 1;
  180. /* 6 iterations to converge */
  181. for (i = 0; i < 6; i++)
  182. s = (s + EGL_Div(a, s)) >> 1;
  183. return s;
  184. }
  185. #endif //ndef EGL_USE_GPP
  186. /* assume 0 <= x <= 1 and y >= 0 */
  187. static __inline EGL_Fixed
  188. xpow(EGL_Fixed x, EGL_Fixed y) {
  189. I32 exp;
  190. EGL_Fixed p, f = x;
  191. //#define __POW_LOW_PREC
  192. /* absolute error < 0.009, more than good enough for 5-bit color */
  193. static const U16 __gl_log_tab[] = { /* domain .5 - 1.0 */
  194. 0xffff, 0xd47f, 0xad96, 0x8a62, 0x6a3f, 0x4caf, 0x3151, 0x17d6, 0x0000
  195. };
  196. static const U16 __gl_alog_tab[] = { /* domain 0 - 1.0 */
  197. 0xffff, 0xeac0, 0xd744, 0xc567, 0xb504, 0xa5fe, 0x9837, 0x8b95, 0x8000
  198. };
  199. if (y == EGL_ZERO || x == EGL_ONE)
  200. return EGL_ONE;
  201. if (x == EGL_ZERO)
  202. return EGL_ZERO;
  203. exp = 15;
  204. if (f & 0xff00) { exp -= 8; f >>= 8; }
  205. if (f & 0xf0) { exp -= 4; f >>= 4; }
  206. if (f & 0xc) { exp -= 2; f >>= 2; }
  207. if (f & 0x2) { exp -= 1; }
  208. f = x << exp;
  209. //printf("f/x/exp %f %f %d %x\n", __GL_F_2_FLOAT(f), __GL_F_2_FLOAT(x), exp, x);
  210. /* compute log base 2 */
  211. x = (f&0x0fff)<<4;
  212. f = (f >> 12)&0x7;
  213. p = EGL_Mul(__gl_log_tab[f+1]-__gl_log_tab[f],x) + __gl_log_tab[f];
  214. //printf("p %f x %f\n", __GL_F_2_FLOAT(p), __GL_F_2_FLOAT(x));
  215. p = EGL_Mul(p, y) + y*exp;
  216. //printf("np %f \n", __GL_F_2_FLOAT(p));
  217. /* compute antilog (2^p) */
  218. exp = EGL_IntFromFixed(p);
  219. p = EGL_FractionFromFixed(p);
  220. //printf("exp = %d frac %f\n", exp, __GL_F_2_FLOAT(p));
  221. x = (p&0x1fff)<<3;
  222. p = p >> 13;
  223. return (EGL_Mul(__gl_alog_tab[p+1]-__gl_alog_tab[p],x)+
  224. __gl_alog_tab[p])>>exp;
  225. }
  226. // --------------------------------------------------------------------------
  227. // Exponentiation function
  228. //
  229. // Parameters:
  230. // value - the basis; assume 0 <= value <= 1
  231. // exponent - the exponent, exponent >= 0
  232. // --------------------------------------------------------------------------
  233. OGLES_API EGL_Fixed EGL_Power(EGL_Fixed a, EGL_Fixed n) {
  234. #if (defined(ARM) || defined(_ARM_))
  235. return xpow(a, n);
  236. #else
  237. return EGL_FixedFromFloat(pow(EGL_FloatFromFixed(a), EGL_FloatFromFixed(n)));
  238. #endif
  239. }