poly_atan.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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.   
  57.   sign1 = getsign(st0_ptr);
  58.   sign2 = getsign(st1_ptr);
  59.   if ( st0_tag == TAG_Valid )
  60.     {
  61.       exponent = exponent(st0_ptr);
  62.     }
  63.   else
  64.     {
  65.       /* This gives non-compatible stack contents... */
  66.       FPU_to_exp16(st0_ptr, st0_ptr);
  67.       exponent = exponent16(st0_ptr);
  68.     }
  69.   if ( st1_tag == TAG_Valid )
  70.     {
  71.       exponent -= exponent(st1_ptr);
  72.     }
  73.   else
  74.     {
  75.       /* This gives non-compatible stack contents... */
  76.       FPU_to_exp16(st1_ptr, st1_ptr);
  77.       exponent -= exponent16(st1_ptr);
  78.     }
  79.   if ( (exponent < 0) || ((exponent == 0) &&
  80.   ((st0_ptr->sigh < st1_ptr->sigh) ||
  81.    ((st0_ptr->sigh == st1_ptr->sigh) &&
  82.     (st0_ptr->sigl < st1_ptr->sigl))) ) )
  83.     {
  84.       inverted = 1;
  85.       Numer.lsw = Denom.lsw = 0;
  86.       XSIG_LL(Numer) = significand(st0_ptr);
  87.       XSIG_LL(Denom) = significand(st1_ptr);
  88.     }
  89.   else
  90.     {
  91.       inverted = 0;
  92.       exponent = -exponent;
  93.       Numer.lsw = Denom.lsw = 0;
  94.       XSIG_LL(Numer) = significand(st1_ptr);
  95.       XSIG_LL(Denom) = significand(st0_ptr);
  96.      }
  97.   div_Xsig(&Numer, &Denom, &argSignif);
  98.   exponent += norm_Xsig(&argSignif);
  99.   if ( (exponent >= -1)
  100.       || ((exponent == -2) && (argSignif.msw > 0xd413ccd0)) )
  101.     {
  102.       /* The argument is greater than sqrt(2)-1 (=0.414213562...) */
  103.       /* Convert the argument by an identity for atan */
  104.       transformed = 1;
  105.       if ( exponent >= 0 )
  106. {
  107. #ifdef PARANOID
  108.   if ( !( (exponent == 0) && 
  109.  (argSignif.lsw == 0) && (argSignif.midw == 0) &&
  110.  (argSignif.msw == 0x80000000) ) )
  111.     {
  112.       EXCEPTION(EX_INTERNAL|0x104);  /* There must be a logic error */
  113.       return;
  114.     }
  115. #endif /* PARANOID */
  116.   argSignif.msw = 0;   /* Make the transformed arg -> 0.0 */
  117. }
  118.       else
  119. {
  120.   Numer.lsw = Denom.lsw = argSignif.lsw;
  121.   XSIG_LL(Numer) = XSIG_LL(Denom) = XSIG_LL(argSignif);
  122.   if ( exponent < -1 )
  123.     shr_Xsig(&Numer, -1-exponent);
  124.   negate_Xsig(&Numer);
  125.       
  126.   shr_Xsig(&Denom, -exponent);
  127.   Denom.msw |= 0x80000000;
  128.       
  129.   div_Xsig(&Numer, &Denom, &argSignif);
  130.   exponent = -1 + norm_Xsig(&argSignif);
  131. }
  132.     }
  133.   else
  134.     {
  135.       transformed = 0;
  136.     }
  137.   argSq.lsw = argSignif.lsw; argSq.midw = argSignif.midw;
  138.   argSq.msw = argSignif.msw;
  139.   mul_Xsig_Xsig(&argSq, &argSq);
  140.   
  141.   argSqSq.lsw = argSq.lsw; argSqSq.midw = argSq.midw; argSqSq.msw = argSq.msw;
  142.   mul_Xsig_Xsig(&argSqSq, &argSqSq);
  143.   accumulatore.lsw = argSq.lsw;
  144.   XSIG_LL(accumulatore) = XSIG_LL(argSq);
  145.   shr_Xsig(&argSq, 2*(-1-exponent-1));
  146.   shr_Xsig(&argSqSq, 4*(-1-exponent-1));
  147.   /* Now have argSq etc with binary point at the left
  148.      .1xxxxxxxx */
  149.   /* Do the basic fixed point polynomial evaluation */
  150.   accumulator.msw = accumulator.midw = accumulator.lsw = 0;
  151.   polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq),
  152.    oddplterms, HIPOWERop-1);
  153.   mul64_Xsig(&accumulator, &XSIG_LL(argSq));
  154.   negate_Xsig(&accumulator);
  155.   polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms, HIPOWERon-1);
  156.   negate_Xsig(&accumulator);
  157.   add_two_Xsig(&accumulator, &fixedpterm, &dummy_exp);
  158.   mul64_Xsig(&accumulatore, &denomterm);
  159.   shr_Xsig(&accumulatore, 1 + 2*(-1-exponent));
  160.   accumulatore.msw |= 0x80000000;
  161.   div_Xsig(&accumulator, &accumulatore, &accumulator);
  162.   mul_Xsig_Xsig(&accumulator, &argSignif);
  163.   mul_Xsig_Xsig(&accumulator, &argSq);
  164.   shr_Xsig(&accumulator, 3);
  165.   negate_Xsig(&accumulator);
  166.   add_Xsig_Xsig(&accumulator, &argSignif);
  167.   if ( transformed )
  168.     {
  169.       /* compute pi/4 - accumulator */
  170.       shr_Xsig(&accumulator, -1-exponent);
  171.       negate_Xsig(&accumulator);
  172.       add_Xsig_Xsig(&accumulator, &pi_signif);
  173.       exponent = -1;
  174.     }
  175.   if ( inverted )
  176.     {
  177.       /* compute pi/2 - accumulator */
  178.       shr_Xsig(&accumulator, -exponent);
  179.       negate_Xsig(&accumulator);
  180.       add_Xsig_Xsig(&accumulator, &pi_signif);
  181.       exponent = 0;
  182.     }
  183.   if ( sign1 )
  184.     {
  185.       /* compute pi - accumulator */
  186.       shr_Xsig(&accumulator, 1 - exponent);
  187.       negate_Xsig(&accumulator);
  188.       add_Xsig_Xsig(&accumulator, &pi_signif);
  189.       exponent = 1;
  190.     }
  191.   exponent += round_Xsig(&accumulator);
  192.   significand(st1_ptr) = XSIG_LL(accumulator);
  193.   setexponent16(st1_ptr, exponent);
  194.   tag = FPU_round(st1_ptr, 1, 0, FULL_PRECISION, sign2);
  195.   FPU_settagi(1, tag);
  196.   set_precision_flag_up();  /* We do not really know if up or down,
  197.        use this as the default. */
  198. }