poly_atan.c 6.3 KB

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