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

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