poly_atan.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*---------------------------------------------------------------------------+
  2. | poly_atan.c |
  3. | |
  4. | Compute the arctan of a FPU_REG, using a polynomial approximation. |
  5. | |
  6. | Copyright (C) 1992,1993,1994,1997 |
  7. | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
  8. | E-mail billm@suburbia.net |
  9. | |
  10. | |
  11. +---------------------------------------------------------------------------*/
  12. #include "exception.h"
  13. #include "reg_constant.h"
  14. #include "fpu_emu.h"
  15. #include "fpu_system.h"
  16. #include "status_w.h"
  17. #include "control_w.h"
  18. #include "poly.h"
  19. #define HIPOWERon 6 /* odd poly, negative terms */
  20. static const unsigned long long oddnegterms[HIPOWERon] =
  21. {
  22. 0x0000000000000000LL, /* Dummy (not for - 1.0) */
  23. 0x015328437f756467LL,
  24. 0x0005dda27b73dec6LL,
  25. 0x0000226bf2bfb91aLL,
  26. 0x000000ccc439c5f7LL,
  27. 0x0000000355438407LL
  28. } ;
  29. #define HIPOWERop 6 /* odd poly, positive terms */
  30. static const unsigned long long oddplterms[HIPOWERop] =
  31. {
  32. /* 0xaaaaaaaaaaaaaaabLL, transferred to fixedpterm[] */
  33. 0x0db55a71875c9ac2LL,
  34. 0x0029fce2d67880b0LL,
  35. 0x0000dfd3908b4596LL,
  36. 0x00000550fd61dab4LL,
  37. 0x0000001c9422b3f9LL,
  38. 0x000000003e3301e1LL
  39. };
  40. static const unsigned long long denomterm = 0xebd9b842c5c53a0eLL;
  41. static const Xsig fixedpterm = MK_XSIG(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa);
  42. static const Xsig pi_signif = MK_XSIG(0xc90fdaa2, 0x2168c234, 0xc4c6628b);
  43. /*--- poly_atan() -----------------------------------------------------------+
  44. | |
  45. +---------------------------------------------------------------------------*/
  46. void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
  47. FPU_REG *st1_ptr, u_char st1_tag)
  48. {
  49. u_char transformed, inverted,
  50. sign1, sign2;
  51. int exponent;
  52. long int dummy_exp;
  53. Xsig accumulator, Numer, Denom, accumulatore, argSignif,
  54. argSq, argSqSq;
  55. u_char tag;
  56. sign1 = getsign(st0_ptr);
  57. sign2 = getsign(st1_ptr);
  58. if ( st0_tag == TAG_Valid )
  59. {
  60. exponent = exponent(st0_ptr);
  61. }
  62. else
  63. {
  64. /* This gives non-compatible stack contents... */
  65. FPU_to_exp16(st0_ptr, st0_ptr);
  66. exponent = exponent16(st0_ptr);
  67. }
  68. if ( st1_tag == TAG_Valid )
  69. {
  70. exponent -= exponent(st1_ptr);
  71. }
  72. else
  73. {
  74. /* This gives non-compatible stack contents... */
  75. FPU_to_exp16(st1_ptr, st1_ptr);
  76. exponent -= exponent16(st1_ptr);
  77. }
  78. if ( (exponent < 0) || ((exponent == 0) &&
  79. ((st0_ptr->sigh < st1_ptr->sigh) ||
  80. ((st0_ptr->sigh == st1_ptr->sigh) &&
  81. (st0_ptr->sigl < st1_ptr->sigl))) ) )
  82. {
  83. inverted = 1;
  84. Numer.lsw = Denom.lsw = 0;
  85. XSIG_LL(Numer) = significand(st0_ptr);
  86. XSIG_LL(Denom) = significand(st1_ptr);
  87. }
  88. else
  89. {
  90. inverted = 0;
  91. exponent = -exponent;
  92. Numer.lsw = Denom.lsw = 0;
  93. XSIG_LL(Numer) = significand(st1_ptr);
  94. XSIG_LL(Denom) = significand(st0_ptr);
  95. }
  96. div_Xsig(&Numer, &Denom, &argSignif);
  97. exponent += norm_Xsig(&argSignif);
  98. if ( (exponent >= -1)
  99. || ((exponent == -2) && (argSignif.msw > 0xd413ccd0)) )
  100. {
  101. /* The argument is greater than sqrt(2)-1 (=0.414213562...) */
  102. /* Convert the argument by an identity for atan */
  103. transformed = 1;
  104. if ( exponent >= 0 )
  105. {
  106. #ifdef PARANOID
  107. if ( !( (exponent == 0) &&
  108. (argSignif.lsw == 0) && (argSignif.midw == 0) &&
  109. (argSignif.msw == 0x80000000) ) )
  110. {
  111. EXCEPTION(EX_INTERNAL|0x104); /* There must be a logic error */
  112. return;
  113. }
  114. #endif /* PARANOID */
  115. argSignif.msw = 0; /* Make the transformed arg -> 0.0 */
  116. }
  117. else
  118. {
  119. Numer.lsw = Denom.lsw = argSignif.lsw;
  120. XSIG_LL(Numer) = XSIG_LL(Denom) = XSIG_LL(argSignif);
  121. if ( exponent < -1 )
  122. shr_Xsig(&Numer, -1-exponent);
  123. negate_Xsig(&Numer);
  124. shr_Xsig(&Denom, -exponent);
  125. Denom.msw |= 0x80000000;
  126. div_Xsig(&Numer, &Denom, &argSignif);
  127. exponent = -1 + norm_Xsig(&argSignif);
  128. }
  129. }
  130. else
  131. {
  132. transformed = 0;
  133. }
  134. argSq.lsw = argSignif.lsw; argSq.midw = argSignif.midw;
  135. argSq.msw = argSignif.msw;
  136. mul_Xsig_Xsig(&argSq, &argSq);
  137. argSqSq.lsw = argSq.lsw; argSqSq.midw = argSq.midw; argSqSq.msw = argSq.msw;
  138. mul_Xsig_Xsig(&argSqSq, &argSqSq);
  139. accumulatore.lsw = argSq.lsw;
  140. XSIG_LL(accumulatore) = XSIG_LL(argSq);
  141. shr_Xsig(&argSq, 2*(-1-exponent-1));
  142. shr_Xsig(&argSqSq, 4*(-1-exponent-1));
  143. /* Now have argSq etc with binary point at the left
  144. .1xxxxxxxx */
  145. /* Do the basic fixed point polynomial evaluation */
  146. accumulator.msw = accumulator.midw = accumulator.lsw = 0;
  147. polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq),
  148. oddplterms, HIPOWERop-1);
  149. mul64_Xsig(&accumulator, &XSIG_LL(argSq));
  150. negate_Xsig(&accumulator);
  151. polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms, HIPOWERon-1);
  152. negate_Xsig(&accumulator);
  153. add_two_Xsig(&accumulator, &fixedpterm, &dummy_exp);
  154. mul64_Xsig(&accumulatore, &denomterm);
  155. shr_Xsig(&accumulatore, 1 + 2*(-1-exponent));
  156. accumulatore.msw |= 0x80000000;
  157. div_Xsig(&accumulator, &accumulatore, &accumulator);
  158. mul_Xsig_Xsig(&accumulator, &argSignif);
  159. mul_Xsig_Xsig(&accumulator, &argSq);
  160. shr_Xsig(&accumulator, 3);
  161. negate_Xsig(&accumulator);
  162. add_Xsig_Xsig(&accumulator, &argSignif);
  163. if ( transformed )
  164. {
  165. /* compute pi/4 - accumulator */
  166. shr_Xsig(&accumulator, -1-exponent);
  167. negate_Xsig(&accumulator);
  168. add_Xsig_Xsig(&accumulator, &pi_signif);
  169. exponent = -1;
  170. }
  171. if ( inverted )
  172. {
  173. /* compute pi/2 - accumulator */
  174. shr_Xsig(&accumulator, -exponent);
  175. negate_Xsig(&accumulator);
  176. add_Xsig_Xsig(&accumulator, &pi_signif);
  177. exponent = 0;
  178. }
  179. if ( sign1 )
  180. {
  181. /* compute pi - accumulator */
  182. shr_Xsig(&accumulator, 1 - exponent);
  183. negate_Xsig(&accumulator);
  184. add_Xsig_Xsig(&accumulator, &pi_signif);
  185. exponent = 1;
  186. }
  187. exponent += round_Xsig(&accumulator);
  188. significand(st1_ptr) = XSIG_LL(accumulator);
  189. setexponent16(st1_ptr, exponent);
  190. tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign2);
  191. FPU_settagi(1, tag);
  192. set_precision_flag_up(); /* We do not really know if up or down,
  193. use this as the default. */
  194. }