root/kernel/FPU-emu/poly_tan.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. poly_tan

   1 /*---------------------------------------------------------------------------+
   2  |  poly_tan.c                                                               |
   3  |                                                                           |
   4  | Compute the tan of a FPU_REG, using a polynomial approximation.           |
   5  |                                                                           |
   6  | Copyright (C) 1992,1993                                                   |
   7  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   8  |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
   9  |                                                                           |
  10  |                                                                           |
  11  +---------------------------------------------------------------------------*/
  12 
  13 #include "exception.h"
  14 #include "reg_constant.h"
  15 #include "fpu_emu.h"
  16 #include "control_w.h"
  17 
  18 
  19 #define HIPOWERop       3       /* odd poly, positive terms */
  20 static unsigned short   oddplterms[HIPOWERop][4] =
  21         {
  22         { 0x846a, 0x42d1, 0xb544, 0x921f},
  23         { 0x6fb2, 0x0215, 0x95c0, 0x099c},
  24         { 0xfce6, 0x0cc8, 0x1c9a, 0x0000}
  25         };
  26 
  27 #define HIPOWERon       2       /* odd poly, negative terms */
  28 static unsigned short   oddnegterms[HIPOWERon][4] =
  29         {
  30         { 0x6906, 0xe205, 0x25c8, 0x8838},
  31         { 0x1dd7, 0x3fe3, 0x944e, 0x002c}
  32         };
  33 
  34 #define HIPOWERep       2       /* even poly, positive terms */
  35 static unsigned short   evenplterms[HIPOWERep][4] =
  36         {
  37         { 0xdb8f, 0x3761, 0x1432, 0x2acf},
  38         { 0x16eb, 0x13c1, 0x3099, 0x0003}
  39         };
  40 
  41 #define HIPOWERen       2       /* even poly, negative terms */
  42 static unsigned short   evennegterms[HIPOWERen][4] =
  43         {
  44         { 0x3a7c, 0xe4c5, 0x7f87, 0x2945},
  45         { 0x572b, 0x664c, 0xc543, 0x018c}
  46         };
  47 
  48 
  49 /*--- poly_tan() ------------------------------------------------------------+
  50  |                                                                           |
  51  +---------------------------------------------------------------------------*/
  52 void    poly_tan(FPU_REG *arg, FPU_REG *y_reg)
     /* [previous][next][first][last][top][bottom][index][help] */
  53 {
  54   char          invert = 0;
  55   short         exponent;
  56   FPU_REG       odd_poly, even_poly, pos_poly, neg_poly;
  57   FPU_REG       argSq;
  58   long long     arg_signif, argSqSq;
  59   
  60 
  61   exponent = arg->exp - EXP_BIAS;
  62   
  63   if ( arg->tag == TW_Zero )
  64     {
  65       /* Return 0.0 */
  66       reg_move(&CONST_Z, y_reg);
  67       return;
  68     }
  69 
  70   if ( exponent >= -1 )
  71     {
  72       /* argument is in the range  [0.5 .. 1.0] */
  73       if ( exponent >= 0 )
  74         {
  75 #ifdef PARANOID
  76           if ( (exponent == 0) && 
  77               (arg->sigl == 0) && (arg->sigh == 0x80000000) )
  78 #endif PARANOID
  79             {
  80               arith_overflow(y_reg);
  81               return;
  82             }
  83 #ifdef PARANOID
  84           EXCEPTION(EX_INTERNAL|0x104); /* There must be a logic error */
  85 #endif PARANOID
  86         }
  87       /* The argument is in the range  [0.5 .. 1.0) */
  88       /* Convert the argument to a number in the range  (0.0 .. 0.5] */
  89       *((long long *)(&arg->sigl)) = - *((long long *)(&arg->sigl));
  90       normalize(arg);   /* Needed later */
  91       exponent = arg->exp - EXP_BIAS;
  92       invert = 1;
  93     }
  94 
  95 #ifdef PARANOID
  96   if ( arg->sign != 0 ) /* Can't hack a number < 0.0 */
  97     { arith_invalid(y_reg); return; }
  98 #endif PARANOID
  99 
 100   *(long long *)&arg_signif = *(long long *)&(arg->sigl);
 101   if ( exponent < -1 )
 102     {
 103       /* shift the argument right by the required places */
 104       if ( shrx(&arg_signif, -1-exponent) >= 0x80000000U )
 105         arg_signif++;   /* round up */
 106     }
 107 
 108   mul64(&arg_signif, &arg_signif, (long long *)(&argSq.sigl));
 109   mul64((long long *)(&argSq.sigl), (long long *)(&argSq.sigl), &argSqSq);
 110 
 111   /* will be a valid positive nr with expon = 0 */
 112   *(short *)&(pos_poly.sign) = 0;
 113   pos_poly.exp = EXP_BIAS;
 114 
 115   /* Do the basic fixed point polynomial evaluation */
 116   polynomial(&pos_poly.sigl, (unsigned *)&argSqSq, oddplterms, HIPOWERop-1);
 117 
 118   /* will be a valid positive nr with expon = 0 */
 119   *(short *)&(neg_poly.sign) = 0;
 120   neg_poly.exp = EXP_BIAS;
 121 
 122   /* Do the basic fixed point polynomial evaluation */
 123   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq, oddnegterms, HIPOWERon-1);
 124   mul64((long long *)(&argSq.sigl), (long long *)(&neg_poly.sigl),
 125         (long long *)(&neg_poly.sigl));
 126 
 127   /* Subtract the mantissas */
 128   *((long long *)(&pos_poly.sigl)) -= *((long long *)(&neg_poly.sigl));
 129 
 130   /* Convert to 64 bit signed-compatible */
 131   pos_poly.exp -= 1;
 132 
 133   reg_move(&pos_poly, &odd_poly);
 134   normalize(&odd_poly);
 135   
 136   reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION);
 137   reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd polynomial */
 138 
 139 
 140   /* will be a valid positive nr with expon = 0 */
 141   *(short *)&(pos_poly.sign) = 0;
 142   pos_poly.exp = EXP_BIAS;
 143   
 144   /* Do the basic fixed point polynomial evaluation */
 145   polynomial(&pos_poly.sigl, (unsigned *)&argSqSq, evenplterms, HIPOWERep-1);
 146   mul64((long long *)(&argSq.sigl),
 147         (long long *)(&pos_poly.sigl), (long long *)(&pos_poly.sigl));
 148   
 149   /* will be a valid positive nr with expon = 0 */
 150   *(short *)&(neg_poly.sign) = 0;
 151   neg_poly.exp = EXP_BIAS;
 152 
 153   /* Do the basic fixed point polynomial evaluation */
 154   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq, evennegterms, HIPOWERen-1);
 155 
 156   /* Subtract the mantissas */
 157   *((long long *)(&neg_poly.sigl)) -= *((long long *)(&pos_poly.sigl));
 158   /* and multiply by argSq */
 159 
 160   /* Convert argSq to a valid reg number */
 161   *(short *)&(argSq.sign) = 0;
 162   argSq.exp = EXP_BIAS - 1;
 163   normalize(&argSq);
 164 
 165   /* Convert to 64 bit signed-compatible */
 166   neg_poly.exp -= 1;
 167 
 168   reg_move(&neg_poly, &even_poly);
 169   normalize(&even_poly);
 170 
 171   reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION);
 172   reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION);
 173   reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION);  /* This is just the even polynomial */
 174 
 175   /* Now ready to copy the results */
 176   if ( invert )
 177     { reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION); }
 178   else
 179     { reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION); }
 180 
 181 }

/* [previous][next][first][last][top][bottom][index][help] */