poly_atan.c 6.2 KB

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