|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.