Annotation of coherent/b/kernel/emulator/poly_atan.c, revision 1.1

1.1     ! root        1: /*---------------------------------------------------------------------------+
        !             2:  |  p_atan.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 [email protected]    |
        !             8:  |                                                                           |
        !             9:  |                                                                           |
        !            10:  +---------------------------------------------------------------------------*/
        !            11: 
        !            12: #include "fpu_system.h"
        !            13: #include "exception.h"
        !            14: #include "reg_constant.h"
        !            15: #include "fpu_emu.h"
        !            16: 
        !            17: 
        !            18: #define        HIPOWERon       6       /* odd poly, negative terms */
        !            19: static unsigned oddnegterms[HIPOWERon][2] =
        !            20: {
        !            21:   { 0x00000000, 0x00000000 }, /* for + 1.0 */
        !            22:   { 0x763b6f3d, 0x1adc4428 },
        !            23:   { 0x20f0630b, 0x0502909d },
        !            24:   { 0x4e825578, 0x0198ce38 },
        !            25:   { 0x22b7cb87, 0x008da6e3 },
        !            26:   { 0x9b30ca03, 0x00239c79 }
        !            27: } ;
        !            28: 
        !            29: #define        HIPOWERop       6       /* odd poly, positive terms */
        !            30: static unsigned        oddplterms[HIPOWERop][2] =
        !            31: {
        !            32:   { 0xa6f67cb8, 0x94d910bd },
        !            33:   { 0xa02ffab4, 0x0a43cb45 },
        !            34:   { 0x04265e6b, 0x02bf5655 },
        !            35:   { 0x0a728914, 0x00f280f7 },
        !            36:   { 0x6d640e01, 0x004d6556 },
        !            37:   { 0xf1dd2dbf, 0x000a530a }
        !            38: };
        !            39: 
        !            40: 
        !            41: static unsigned denomterm[2] =
        !            42: { 0xfc4bd208, 0xea2e6612 };
        !            43: 
        !            44: 
        !            45: 
        !            46: /*--- poly_atan() -----------------------------------------------------------+
        !            47:  |                                                                           |
        !            48:  +---------------------------------------------------------------------------*/
        !            49: void   poly_atan(FPU_REG *arg)
        !            50: {
        !            51:   char         recursions = 0;
        !            52:   short                exponent;
        !            53:   FPU_REG       odd_poly, even_poly, pos_poly, neg_poly;
        !            54:   FPU_REG       argSq;
        !            55:   long long     arg_signif, argSqSq;
        !            56:   
        !            57: 
        !            58: #ifdef PARANOID
        !            59:   if ( arg->sign != 0 )        /* Can't hack a number < 0.0 */
        !            60:     { arith_invalid(arg); return; }
        !            61: #endif PARANOID
        !            62: 
        !            63:   exponent = arg->exp - EXP_BIAS;
        !            64:   
        !            65:   if ( arg->tag == TW_Zero )
        !            66:     {
        !            67:       /* Return 0.0 */
        !            68:       reg_move(&CONST_Z, arg);
        !            69:       return;
        !            70:     }
        !            71:   
        !            72:   if ( exponent >= -2 )
        !            73:     {
        !            74:       /* argument is in the range  [0.25 .. 1.0] */
        !            75:       if ( exponent >= 0 )
        !            76:        {
        !            77: #ifdef PARANOID
        !            78:          if ( (exponent == 0) && 
        !            79:              (arg->sigl == 0) && (arg->sigh == 0x80000000) )
        !            80: #endif PARANOID
        !            81:            {
        !            82:              reg_move(&CONST_PI4, arg);
        !            83:              return;
        !            84:            }
        !            85: #ifdef PARANOID
        !            86:          EXCEPTION(EX_INTERNAL|0x104); /* There must be a logic error */
        !            87: #endif PARANOID
        !            88:        }
        !            89: 
        !            90:       /* If the argument is greater than sqrt(2)-1 (=0.414213562...) */
        !            91:       /* convert the argument by an identity for atan */
        !            92:       if ( (exponent >= -1) || (arg->sigh > 0xd413ccd0) )
        !            93:        {
        !            94:          FPU_REG numerator, denom;
        !            95: 
        !            96:          recursions++;
        !            97: 
        !            98:          arg_signif = *(long long *)&(arg->sigl);
        !            99:          if ( exponent < -1 )
        !           100:            {
        !           101:              if ( shrx(&arg_signif, -1-exponent) >= 0x80000000U )
        !           102:                arg_signif++;   /* round up */
        !           103:            }
        !           104:          *(long long *)&(numerator.sigl) = -arg_signif;
        !           105:          numerator.exp = EXP_BIAS - 1;
        !           106:          normalize(&numerator);                       /* 1 - arg */
        !           107: 
        !           108:          arg_signif = *(long long *)&(arg->sigl);
        !           109:          if ( shrx(&arg_signif, -exponent) >= 0x80000000U )
        !           110:            arg_signif++;       /* round up */
        !           111:          *(long long *)&(denom.sigl) = arg_signif;
        !           112:          denom.sigh |= 0x80000000;                    /* 1 + arg */
        !           113: 
        !           114:          arg->exp = numerator.exp;
        !           115:          reg_u_div((long long *)&(numerator.sigl),
        !           116:                    (long long *)&(denom.sigl), arg);
        !           117: 
        !           118:          exponent = arg->exp - EXP_BIAS;
        !           119:        }
        !           120:     }
        !           121: 
        !           122:   *(long long *)&arg_signif = *(long long *)&(arg->sigl);
        !           123: 
        !           124: #ifdef PARANOID
        !           125:   /* This must always be true */
        !           126:   if ( exponent >= -1 )
        !           127:     {
        !           128:       EXCEPTION(EX_INTERNAL|0x120);    /* There must be a logic error */
        !           129:     }
        !           130: #endif PARANOID
        !           131: 
        !           132:   /* shift the argument right by the required places */
        !           133:   if ( shrx(&arg_signif, -1-exponent) >= 0x80000000U )
        !           134:     arg_signif++;      /* round up */
        !           135:   
        !           136:   /* Now have arg_signif with binary point at the left
        !           137:      .1xxxxxxxx */
        !           138:   mul64(&arg_signif, &arg_signif, (long long *)(&argSq.sigl));
        !           139:   mul64((long long *)(&argSq.sigl), (long long *)(&argSq.sigl), &argSqSq);
        !           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,
        !           147:             (unsigned short (*)[4])oddplterms, HIPOWERop-1);
        !           148:   mul64((long long *)(&argSq.sigl), (long long *)(&pos_poly.sigl),
        !           149:        (long long *)(&pos_poly.sigl));
        !           150: 
        !           151:   /* will be a valid positive nr with expon = 0 */
        !           152:   *(short *)&(neg_poly.sign) = 0;
        !           153:   neg_poly.exp = EXP_BIAS;
        !           154: 
        !           155:   /* Do the basic fixed point polynomial evaluation */
        !           156:   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq,
        !           157:             (unsigned short (*)[4])oddnegterms, HIPOWERon-1);
        !           158: 
        !           159:   /* Subtract the mantissas */
        !           160:   *((long long *)(&pos_poly.sigl)) -= *((long long *)(&neg_poly.sigl));
        !           161: 
        !           162:   reg_move(&pos_poly, &odd_poly);
        !           163:   poly_add_1(&odd_poly);
        !           164: 
        !           165:   reg_u_mul(&odd_poly, arg, &odd_poly);        /* The complete odd polynomial */
        !           166:   odd_poly.exp -= EXP_BIAS - 1;
        !           167: 
        !           168:   /* will be a valid positive nr with expon = 0 */
        !           169:   *(short *)&(even_poly.sign) = 0;
        !           170: 
        !           171:   mul64((long long *)(&argSq.sigl),
        !           172:        (long long *)(&denomterm), (long long *)(&even_poly.sigl));
        !           173: 
        !           174:   poly_add_1(&even_poly);
        !           175: 
        !           176:   reg_div(&odd_poly, &even_poly, arg);
        !           177: 
        !           178:   if ( recursions )
        !           179:     reg_sub(&CONST_PI4, arg, arg);
        !           180: }
        !           181: 
        !           182: 
        !           183: /* The argument to this function must be polynomial() compatible,
        !           184:    i.e. have an exponent (not checked) of EXP_BIAS-1 but need not
        !           185:    be normalized.
        !           186:    This function adds 1.0 to the (assumed positive) argument. */
        !           187: void poly_add_1(FPU_REG *src)
        !           188: {
        !           189: /* Rounding in a consistent direction produces better results
        !           190:    for the use of this function in poly_atan. Simple truncation
        !           191:    is used here instead of round-to-nearest. */
        !           192: 
        !           193: #ifdef OBSOLETE
        !           194: char round = (src->sigl & 3) == 3;
        !           195: #endif OBSOLETE
        !           196: 
        !           197: shrx(&src->sigl, 1);
        !           198: 
        !           199: #ifdef OBSOLETE
        !           200: if ( round ) (*(long long *)&src->sigl)++;   /* Round to even */
        !           201: #endif OBSOLETE
        !           202: 
        !           203: src->sigh |= 0x80000000;
        !           204: 
        !           205: src->exp = EXP_BIAS;
        !           206: 
        !           207: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.