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