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           return;
  86 #endif PARANOID
  87         }
  88       /* The argument is in the range  [0.5 .. 1.0) */
  89       /* Convert the argument to a number in the range  (0.0 .. 0.5] */
  90       *((long long *)(&arg->sigl)) = - *((long long *)(&arg->sigl));
  91       normalize(arg);   /* Needed later */
  92       exponent = arg->exp - EXP_BIAS;
  93       invert = 1;
  94     }
  95 
  96 #ifdef PARANOID
  97   if ( arg->sign != 0 ) /* Can't hack a number < 0.0 */
  98     { arith_invalid(y_reg); return; }  /* Need a positive number */
  99 #endif PARANOID
 100 
 101   *(long long *)&arg_signif = *(long long *)&(arg->sigl);
 102   if ( exponent < -1 )
 103     {
 104       /* shift the argument right by the required places */
 105       if ( shrx(&arg_signif, -1-exponent) >= 0x80000000U )
 106         arg_signif++;   /* round up */
 107     }
 108 
 109   mul64(&arg_signif, &arg_signif, (long long *)(&argSq.sigl));
 110   mul64((long long *)(&argSq.sigl), (long long *)(&argSq.sigl), &argSqSq);
 111 
 112   /* will be a valid positive nr with expon = 0 */
 113   *(short *)&(pos_poly.sign) = 0;
 114   pos_poly.exp = EXP_BIAS;
 115 
 116   /* Do the basic fixed point polynomial evaluation */
 117   polynomial(&pos_poly.sigl, (unsigned *)&argSqSq, oddplterms, HIPOWERop-1);
 118 
 119   /* will be a valid positive nr with expon = 0 */
 120   *(short *)&(neg_poly.sign) = 0;
 121   neg_poly.exp = EXP_BIAS;
 122 
 123   /* Do the basic fixed point polynomial evaluation */
 124   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq, oddnegterms, HIPOWERon-1);
 125   mul64((long long *)(&argSq.sigl), (long long *)(&neg_poly.sigl),
 126         (long long *)(&neg_poly.sigl));
 127 
 128   /* Subtract the mantissas */
 129   *((long long *)(&pos_poly.sigl)) -= *((long long *)(&neg_poly.sigl));
 130 
 131   /* Convert to 64 bit signed-compatible */
 132   pos_poly.exp -= 1;
 133 
 134   reg_move(&pos_poly, &odd_poly);
 135   normalize(&odd_poly);
 136   
 137   reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION);
 138   reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd polynomial */
 139 
 140 
 141   /* will be a valid positive nr with expon = 0 */
 142   *(short *)&(pos_poly.sign) = 0;
 143   pos_poly.exp = EXP_BIAS;
 144   
 145   /* Do the basic fixed point polynomial evaluation */
 146   polynomial(&pos_poly.sigl, (unsigned *)&argSqSq, evenplterms, HIPOWERep-1);
 147   mul64((long long *)(&argSq.sigl),
 148         (long long *)(&pos_poly.sigl), (long long *)(&pos_poly.sigl));
 149   
 150   /* will be a valid positive nr with expon = 0 */
 151   *(short *)&(neg_poly.sign) = 0;
 152   neg_poly.exp = EXP_BIAS;
 153 
 154   /* Do the basic fixed point polynomial evaluation */
 155   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq, evennegterms, HIPOWERen-1);
 156 
 157   /* Subtract the mantissas */
 158   *((long long *)(&neg_poly.sigl)) -= *((long long *)(&pos_poly.sigl));
 159   /* and multiply by argSq */
 160 
 161   /* Convert argSq to a valid reg number */
 162   *(short *)&(argSq.sign) = 0;
 163   argSq.exp = EXP_BIAS - 1;
 164   normalize(&argSq);
 165 
 166   /* Convert to 64 bit signed-compatible */
 167   neg_poly.exp -= 1;
 168 
 169   reg_move(&neg_poly, &even_poly);
 170   normalize(&even_poly);
 171 
 172   reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION);
 173   reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION);
 174   reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION);  /* This is just the even polynomial */
 175 
 176   /* Now ready to copy the results */
 177   if ( invert )
 178     { reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION); }
 179   else
 180     { reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION); }
 181 
 182 }

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