#line 129 "rt_fix.nw" #ifndef _RT_FIX_H_ #define _RT_FIX_H_ /* * Fixed Point Arithmetic Routines * * 1998 Till Christian Siering * */ #line 139 "rt_fix.nw" #include /* Imports MAXLONG and MINLONG */ #ifndef __KERNEL__ # include #else # ifndef LONG_MIN /* needed for debian 2.0 libc2 */ # include /* Imports LONG_MAX */ # define LONG_MIN (- LONG_MAX - 1L) /* which seems to be screwed up */ # endif #endif /* __KERNEL__ */ #line 191 "rt_fix.nw" typedef struct _rt_fix { long _value; /* value of this object */ unsigned short _iwl; /* integer word-length => bits for the mantissa */ unsigned short _errorset; /* set for recording exceptions */ } rt_fix; #line 151 "rt_fix.nw" /* * Number of Bits used to represent the integral and fractional part * of a fixed point number. Bit 32 is used for the sign bit in the * internal two's complement representation. */ #define RT_FIXWL 31 /* * Default integer word length. */ #define DEFAULT_IWL 17 /* * Size of a string to print the string representation of a fixed point number * into. */ #define RT_FIX_STR_REP_SIZE 30 /* * Overflow bit. */ #define RT_FIX_OV 1 /* * Underflow bit. */ #define RT_FIX_UV 2 /* * Undefined result bit. */ #define RT_FIX_UNDEFINED 4 extern const rt_fix rt_fix_0; /* = 0 */ extern const rt_fix rt_fix_1; /* = 1 */ extern const rt_fix rt_fix_min; /* = -2^31 */ extern const rt_fix rt_fix_max; /* = 2^31 - 1 */ extern const rt_fix rt_fix_pi; /* = 3.141... */ #line 198 "rt_fix.nw" /* * clear the error set of a fixed point number. * InOut: * rt_fix *fix pointer to a fixed point number. * Post: * All errors in the error set of fix are cleared. * Out: * 0 if all errors could be cleared * -1 on error */ extern __inline__ short rt_fix_erremptyset(rt_fix *fix) { if(!fix) { return -1; } fix->_errorset = 0; return 0; } /* End of rt_fix_erremptyset */ /* * add a given error to the error set of a fixed point number. * InOut: * rt_fix *fix pointer to a fixed point number. * In: * unsigned short errnum the error to be added * Post: * the error is added to the error set of fix. * Out: * 0 if the error could be added * -1 on error */ extern __inline__ short rt_fix_erraddset(rt_fix *fix, unsigned short errnum) { if(!fix) { return -1; } switch(errnum) { case RT_FIX_OV: case RT_FIX_UV: case RT_FIX_UNDEFINED: fix->_errorset |= errnum; return 0; default: return -1; } } /* End of rt_fix_erraddset */ /* * merge the error sets of two fixed point numbers. * InOut: * rt_fix *target pointer to a fixed point number. * In: * rt_fix source a fixed point number. * Post: * the error set of source is added to the error set of target. * Out: * 0 if the error sets could be merged * -1 on error */ extern __inline__ short rt_fix_errmergeset(rt_fix *target, rt_fix source) { if(!target) { return -1; } target->_errorset |= source._errorset; return 0; } /* End of rt_fix_errmergeset */ /* * delete a given error from the error set of a fixed point number. * InOut: * rt_fix *fix pointer to a fixed point number. * In: * unsigned short errnum the error to be deleted * Post: * the error is deleted from the error set of fix. * Out: * 0 if the error could be deleted * -1 on error */ extern __inline__ short rt_fix_errdelset(rt_fix *fix, unsigned short errnum) { if(!fix) { return -1; } switch(errnum) { case RT_FIX_OV: case RT_FIX_UV: case RT_FIX_UNDEFINED: fix->_errorset &= ~errnum; return 0; default: return -1; } } /* End of rt_fix_errdelset */ /* * set all possible errors in the error set of a fixed point number. * InOut: * rt_fix *fix pointer to a fixed point number. * Post: * all possible errors are set in the error set of fix. * Out: * 0 if all errors could be set * -1 on error */ extern __inline__ short rt_fix_errfillset(rt_fix *fix) { short result = 0; if(!fix) { return -1; } if(rt_fix_erraddset(fix, RT_FIX_OV) == -1) { result = -1; } if(rt_fix_erraddset(fix, RT_FIX_UV) == -1) { result = -1; } if(rt_fix_erraddset(fix, RT_FIX_UNDEFINED) == -1) { result = -1; } return result; } /* End of rt_fix_errfillset */ /* * test, if a fixed point number is error is faulty. * In: * rt_fix fix a fixed point number. * Out: * 1 if fix is faulty * 0 otherwise */ extern __inline__ short rt_fix_errtstset(rt_fix fix) { return (fix._errorset != 0); } /* End of rt_fix_errtstset */ /* * test, if a error is set in the error set of a fixed point number. * In: * rt_fix fix a fixed point number * short errnum the error to be tested * Out: * 1 if errnum is a member of the error set of fix * 0 otherwise */ extern __inline__ short rt_fix_errisset(rt_fix fix, unsigned short errnum) { switch(errnum) { case RT_FIX_OV: case RT_FIX_UV: case RT_FIX_UNDEFINED: if(fix._errorset & errnum) { return 1; } default: return 0; } } /* End of rt_fix_errisset */ /* * get the sign of a fixed point number. * In: * rt_fix arg the fixed point number to get the * sign from. * Out: * 1 if arg is < 0 * 0 else */ extern __inline__ short rt_fix_sign(rt_fix arg) { arg._value &= MINLONG; return arg._value; } /* End of rt_fix_sign */ /* * Computes the absolute value of x. * Out: * The absolute value of x. */ extern __inline__ rt_fix rt_fix_abs(rt_fix fix) { if(fix._value < 0) { fix._value = -fix._value; return fix; } return fix; } /* End of rt_fix_abs */ /* * negate a fixed point number (multiply it by -1). * In: * rt_fix arg the fixed point number to be negated. * Out: * A fixed point number, which is the result of arg * -1. */ extern __inline__ rt_fix rt_fix_neg(rt_fix arg) { arg._value = -arg._value; return arg; } /* End of rt_fix_neg */ /* * initialize a fixed point number with default values. * InOut: * rt_fix *fix pointer to the fixed point number which * is manipulated * Post: * The fixed point number fix is set to 0 and its * integer word length is set to DEFAULT_IWL. */ extern __inline__ short rt_fix_init(rt_fix *fix) { if(!fix) { return 1; } fix->_iwl = DEFAULT_IWL; fix->_value = 0; rt_fix_erremptyset(fix); return 0; } /* End of rt_fix_init */ /* * initialize a fixed point number with a given integer. * InOut: * rt_fix *fix pointer to the fixed point number which * is initialized * In: * int i the integer used for initialization * Out: * 0 on success * 1 on error * Post: * The fixed point number fix is initialized with the * given integer. */ extern __inline__ short rt_fix_init_i(rt_fix *fix, int i) { unsigned short iwl = 1; int p = 1; int tmp_i = i; if(!fix) { return 1; } /* * find out how many bits are needed to represent i. */ if(tmp_i < 0) { tmp_i = -i; } for(iwl = 1; iwl <= RT_FIXWL; iwl++) { if(tmp_i <= p) { break; } p <<= 1; } fix->_iwl = iwl; fix->_value = (long)(i << (RT_FIXWL - fix->_iwl)); rt_fix_erremptyset(fix); return 0; } /* End of rt_fix_init_i */ /* * initialize a fixed point number with a given long. * InOut: * rt_fix *fix pointer to the fixed point number which * is initialized * In: * int l the long used for initialization * Out: * 0 on success * 1 on error * Post: * The fixed point number fix is initialized with the * given long. */ extern __inline__ short rt_fix_init_l(rt_fix *fix, long l) { unsigned short iwl = 1; int p = 1; if(!fix) { return 1; } /* * find out how many bits are needed to represent l. */ for(iwl = 1; iwl <= RT_FIXWL; iwl++) { if(l <= p) break; p <<= 1; } fix->_iwl = iwl; fix->_value = (long)(l << (RT_FIXWL - fix->_iwl)); rt_fix_erremptyset(fix); return 0; } /* End of rt_fix_init_l */ /* * initialize with given 32-Bit-Mask and given integer word length. * InOut: * rt_fix *fix pointer to the fixed point number which * is initialized * In: * long bit_mask the bit_mask used for initialization * unsigned short iwlen the integer word length used for initialization * Out: * 0 on success * 1 on error * Post: * The fixed point number fix is initialized with the * given bit mask and the given integer word length. */ extern __inline__ short rt_fix_init_mask(rt_fix *fix, long bit_mask, unsigned short iwlen) { if(!fix) { return 1; } fix->_iwl = iwlen; fix->_value = bit_mask; rt_fix_erremptyset(fix); return 1; } /* End of rt_fix_init_mask */ #ifndef __KERNEL__ /* * initialize a fixed pointer number with a given double. * InOut: * rt_fix *fix point to the fixed point number which * is initialized * In: * double d the double used for initialization * Out: * 0 on success * 1 on error * Post: * The fixed point number fix is initialized with the * given double. */ extern __inline__ short rt_fix_init_d(rt_fix *fix, double d) { unsigned int iwl = 1; int p = 1; if(!fix) { return 1; } /* * find out how many bits are needed to represent d. */ for(iwl = 1; iwl <= RT_FIXWL; iwl++) { if(fabs(d) <= p) break; p <<= 1; } if(iwl > RT_FIXWL) { if(d >= 0.) { *fix = rt_fix_max; } else { *fix = rt_fix_min; } rt_fix_erraddset(fix, RT_FIX_OV); } else { fix->_iwl = iwl; fix->_value = (long)(d * (1 << (RT_FIXWL - fix->_iwl))); rt_fix_erremptyset(fix); } return 0; } /* End of rt_fix_init_d */ #endif /* * transform a fixed point number to long. * In: * rt_fix fix the fixed point number to be * transformed * Out: * The result of the transformation. */ extern __inline__ long rt_fix_tol(rt_fix fix) { return((long)(fix._value >> (RT_FIXWL - fix._iwl))); } /* End of rt_fix_tol */ /* * transform a fixed point number to a int. * In: * rt_fix fix the fixed point number to be * transformed * Out: * The result of the transformation. */ extern __inline__ int rt_fix_toi(rt_fix fix) { return((int)(fix._value >> (RT_FIXWL - fix._iwl))); } /* End of rt_fix_toi */ #ifndef __KERNEL__ /* * transform a fixed point number to a double. * In: * rt_fix fix the fixed point number to be * transformed * Out: * The result of the transformation. */ extern __inline__ double rt_fix_tod(rt_fix fix) { double result; result = (double)fix._value; return(result / (1 << (RT_FIXWL - fix._iwl))); } /* End of rt_fix_tod */ #endif /* * shift a fixed point number b bits left. * In: * rt_fix arg the fixed point number to be shifted * int b the number of bits arg is shifted. * Pre: * The sum of the integer word length of arg and b is * smaller or equal RT_FIXWL. * Out: * A fixed point number representing arg * 2^b. */ extern __inline__ rt_fix rt_fix_shl(rt_fix arg, int b) { arg._value <<= b; return arg; } /* End of rt_fix_shl */ /* * shift a fixed point number b bits right. * In: * rt_fix arg the fixed point number to be shifted * int b the number of bits arg is shifted. * Out: * A fixed point number representing arg / 2^b. */ extern __inline__ rt_fix rt_fix_shr(rt_fix arg, int b) { arg._value >>= b; return arg; } /* End of rt_fix_shr */ #ifdef NEEDED /* * Transform the internal representation of a fixed point number * into the internal representation with minimal integer word length. * InOut: * rt_fix fix fixed point number whose integer word length is to * be minimized. * Post: * The integer word length of the fixed point number fix is minimized. * The smallest integer word length is one. */ extern __inline__ void rt_fix_min_iwl(rt_fix *fix) { unsigned long mask = 1073741824; /* = 2^30 */ if(fix) { /* * integer word length of fix is minimal */ if(fix->_iwl < 2) { return; } /* * test if fix is negative */ if(fix->_value < 0) { fix->_value = ~fix->_value; while(!(fix->_value & mask) && fix->_iwl > 1) { fix->_value <<= 1; fix->_iwl--; } fix->_value = ~fix->_value; } else { while(!(fix->_value & mask) && fix->_iwl > 1) { fix->_value <<= 1; fix->_iwl--; } } } } /* End of rt_fix_min_iwl */ #endif /* * Transform the internal representation of a fixed point number * into the internal representation with minimal integer word length. * InOut: * rt_fix fix fixed point number whose integer word length is to * be minimized. * Post: * The integer word length of the fixed point number fix is minimized. * The smallest integer word length is one. */ extern __inline__ void rt_fix_min_iwl(rt_fix *fix) { unsigned long mask = 1073741824; /* = 2^30 */ short sign = 0; if(fix) { if(fix->_iwl < 2) { return; } sign = rt_fix_sign(*fix); if(sign) { *fix = rt_fix_neg(*fix); while(!(fix->_value & mask) && fix->_iwl > 1) { fix->_value <<= 1; fix->_iwl--; } *fix = rt_fix_neg(*fix); } else { while(!(fix->_value & mask) && fix->_iwl > 1) { fix->_value <<= 1; fix->_iwl--; } } } } /* End of rt_fix_min_iwl */ /* * Add two fixed point numbers. * In: * rt_fix x the summand * rt_fix y the fixed point number added to x * Out: * A fixed point number representing the result of x + y. * If the result overflows rt_fix_max is returned. */ extern __inline__ rt_fix rt_fix_add(rt_fix x, rt_fix y) { unsigned short iwl = (x._iwl > y._iwl) ? x._iwl + 1 : y._iwl + 1; /* * let the result appear in x. */ rt_fix_errmergeset(&x, y); if(iwl > RT_FIXWL) { x = rt_fix_max; rt_fix_errmergeset(&x, y); rt_fix_erraddset(&x, RT_FIX_OV); return x; } if(x._iwl > y._iwl) { x._value = (x._value >> 1) + (y._value >> (x._iwl - y._iwl + 1)); } else if(x._iwl < y._iwl) { x._value = (x._value >> (y._iwl - x._iwl + 1)) + (y._value >> 1); } else { x._value = (x._value >> 1) + (y._value >> 1); } x._iwl = iwl; rt_fix_min_iwl(&x); return x; } /* End of rt_fix_add */ /* * Subtract to fixed point numbers. * In: * rt_fix x the minuend * rt_fix y the subtrahend * Out: * A fixed point number representing the result of x - y. * If the result overflows rt_fix_max is returned. */ extern __inline__ rt_fix rt_fix_sub(rt_fix x, rt_fix y) { unsigned short iwl = (x._iwl > y._iwl) ? x._iwl + 1 : y._iwl + 1; /* * let the result appear in x. */ rt_fix_errmergeset(&x, y); if(iwl > RT_FIXWL) { x = rt_fix_max; rt_fix_errmergeset(&x, y); rt_fix_erraddset(&x, RT_FIX_OV); return x; } if(x._iwl > y._iwl) { x._value = (x._value >> 1) - (y._value >> (x._iwl - y._iwl + 1)); } else if(x._iwl < y._iwl) { x._value = (x._value >> (y._iwl - x._iwl + 1)) - (y._value >> 1); } else { x._value = (x._value >> 1) - (y._value >> 1); } x._iwl = iwl; rt_fix_min_iwl(&x); return x; } /* End of rt_fix_sub */ /* * Multiply two fixed point numbers. * In: * rt_fix x the multiplicand * rt_fix y the multiplicator * Out: * A fixed point number representing the result of x * y. * If the result overflows rt_fix_max is returned. */ extern __inline__ rt_fix rt_fix_mul(rt_fix x, rt_fix y) { unsigned short iwl = x._iwl + y._iwl; /* * let the result appear in x. */ rt_fix_errmergeset(&x, y); if(iwl > RT_FIXWL) { if(rt_fix_sign(x) ^ rt_fix_sign(y)) { x = rt_fix_min; } else { x = rt_fix_max; } rt_fix_errmergeset(&x, y); rt_fix_erraddset(&x, RT_FIX_OV); return x; } if(y._iwl < iwl) { y._value >>= x._iwl; } if(x._iwl < iwl) { x._value >>= y._iwl; } x._iwl = iwl; __asm__("imull %%ebx\n\t" /* Multiply a * b */ "shrdl %%cl, %%edx, %%eax\n\t" : "=a" (x._value) : "a" (x._value), "b" (y._value), "c" (RT_FIXWL - x._iwl) : "edx"); rt_fix_min_iwl(&x); return x; } /* End of rt_fix_mul */ /* * Divide two fixed point numbers. * In: * rt_fix x the divident * rt_fix y the divisor * Out: * A fixed point number representing the result of x / y. * If the attempt to divide by zero is made rt_fix_max * is returned. */ extern __inline__ rt_fix rt_fix_div(rt_fix x, rt_fix y) { unsigned short iwl = x._iwl; short sign; long tmp; sign = rt_fix_sign(x) ^ rt_fix_sign(y); x = rt_fix_abs(x); y = rt_fix_abs(y); /* * let the result appear in x. */ rt_fix_errmergeset(&x, y); if(y._value == 0) { /* * division by zero */ if(sign) { x = rt_fix_min; } else { x = rt_fix_max; } rt_fix_errmergeset(&x, y); rt_fix_erraddset(&x, RT_FIX_UNDEFINED); return x; } if(x._iwl > y._iwl) { /* * |x| > |y| */ y._value >>= (x._iwl - y._iwl); iwl = x._iwl; if(y._value == 0) { if(sign) { x = rt_fix_min; } else { x = rt_fix_max; } rt_fix_errmergeset(&x, y); rt_fix_erraddset(&x, RT_FIX_UNDEFINED); return x; } } else if(x._iwl < y._iwl) { /* * |x| < |y| */ x._value >>= (y._iwl - x._iwl); iwl = y._iwl; if(x._value == 0) { return rt_fix_0; } } if(rt_fix_toi(y) == 0 || rt_fix_toi(y) == -1) { tmp = y._value; /* * |y| < 1 */ tmp <<= y._iwl; while(!(tmp & (1 << RT_FIXWL))) { tmp <<= 1; iwl++; } iwl = iwl + x._iwl; if(iwl > RT_FIXWL) { if(sign) { x = rt_fix_min; } else { x = rt_fix_max; } rt_fix_errmergeset(&x, y); rt_fix_erraddset(&x, RT_FIX_OV); return x; } } x._iwl = iwl; __asm__("xorl %%edx, %%edx\n\t" /* Clear edx */ "shldl %%cl, %%eax, %%edx\n\t" /* Shift edx left and fill in from eax */ "sall %%cl, %%eax\n\t" /* Shift eax upward */ "idivl %%ebx\n\t" /* Divide (edx:eax) / ebx */ : "=a" (x._value) : "a" (x._value), "b" (y._value), "c" ((unsigned short) (RT_FIXWL - x._iwl)) : "edx"); rt_fix_min_iwl(&x); if(sign) { return rt_fix_neg(x); } else { return x; } } /* End of rt_fix_div */ /* * Test if two fixed point numbers are equal. * In: * rt_fix x a fixed point number * rt_fix y a fixed point number * Out: * 1 if x and y are equal * 0 otherwise */ extern __inline__ short rt_fix_eq(rt_fix x, rt_fix y) { /* * lvalue and rvalue must have the same iwl. */ if(x._iwl > y._iwl) { y._value >>= (x._iwl - y._iwl); } else if(x._iwl < y._iwl) { x._value >>= (y._iwl - x._iwl); } return(x._value == y._value); } /* End of rt_fix_eq */ /* * Test if two fixed point numbers are not equal. * In: * rt_fix x a fixed point number * rt_fix y a fixed point number * Out: * 1 if x and y are not equal * 0 otherwise */ extern __inline__ short rt_fix_neq(rt_fix x, rt_fix y) { /* * lvalue and rvalue must have the same iwl. */ if(x._iwl > y._iwl) { y._value >>= (x._iwl - y._iwl); } else if(x._iwl < y._iwl) { x._value >>= (y._iwl - x._iwl); } return(x._value != y._value); } /* End of rt_fix_neq */ /* * Test if two fixed point numbers are greater-equal. * In: * rt_fix x a fixed point number * rt_fix y a fixed point number * Out: * 1 if x is greater or equal y * 0 otherwise */ extern __inline__ short rt_fix_geq(rt_fix x, rt_fix y) { /* * lvalue and rvalue must have the same iwl. */ if(x._iwl > y._iwl) { y._value >>= (x._iwl - y._iwl); } else if(x._iwl < y._iwl) { x._value >>= (y._iwl - x._iwl); } if(x._value >= y._value) { return 1; } else { return 0; } } /* End of rt_fix_geq */ /* * Test if two fixed point numbers are smaller-equal. * In: * rt_fix x a fixed point number * rt_fix y a fixed point number * Out: * 1 if x is smaller or equal y * 0 otherwise */ extern __inline__ short rt_fix_leq(rt_fix x, rt_fix y) { /* * lvalue and rvalue must have the same iwl. */ if(x._iwl > y._iwl) { y._value >>= (x._iwl - y._iwl); } else if(x._iwl < y._iwl) { x._value >>= (y._iwl - x._iwl); } if(x._value <= y._value) { return 1; } else { return 0; } } /* End of rt_fix_leq */ /* * Test if one fixed point numbers is greater than another. * In: * rt_fix x a fixed point number * rt_fix y a fixed point number * Out: * 1 if x is greater y * 0 otherwise */ extern __inline__ short rt_fix_gtr(rt_fix x, rt_fix y) { /* * lvalue and rvalue must have the same iwl. */ if(x._iwl > y._iwl) { y._value >>= (x._iwl - y._iwl); } else if(x._iwl < y._iwl) { x._value >>= (y._iwl - x._iwl); } if(x._value > y._value) { return 1; } else { return 0; } } /* End of rt_fix_gtr */ /* * Test if one fixed point number is smaller than another. * In: * rt_fix x a fixed point number * rt_fix y a fixed point number * Out: * 1 if x is smaller y * 0 otherwise */ extern __inline__ short rt_fix_lss(rt_fix x, rt_fix y) { /* * lvalue and rvalue must have the same iwl. */ if(x._iwl > y._iwl) { y._value >>= (x._iwl - y._iwl); } else if(x._iwl < y._iwl) { x._value >>= (y._iwl - x._iwl); } if(x._value < y._value) { return 1; } else { return 0; } } /* End of rt_fix_lss */ /************************ * builtin math functions ***********************/ /* * Multiply a fixed point number by integral power of 2. * In: * rt_fix fix fixed point number to be mulitplied * int pow2 exponent of pow(2, pow2) * Out: * On success the result of the multiplication. * On error rt_fix_max. */ #define rt_fix_ldexp(fix, pow2) (rt_fix_shl(arg, b)) /* * Get the fractional part of a fixed point number. * In: * rt_fix fix fixed point number to extract the * fractional part from. * Out: * A fixed point number which contains the fractional * part of fix. */ extern __inline__ rt_fix rt_fix_frac(rt_fix fix) { unsigned int p = 1; long value = fix._value; unsigned int i; fix._value = 0; if(value < 0) { value = -value; for(i = 0; i < (RT_FIXWL - fix._iwl); i++) { if((p & value) > 0) { fix._value += p; } p <<= 1; } fix._value = -fix._value; } else { for(i = 0; i < (RT_FIXWL - fix._iwl); i++) { if((p & value) > 0) { fix._value += p; } p <<= 1; } } return fix; } /* End of frac */ /* * Calculate the largest integral value of a fixed point number * not greater than the value of the fixed point number itself. * In: * rt_fix fix the fixed point number to calculate the largest * integral value from. * Out: * A fixed point number which represents the the largest integral * value not greater than the value of fix. */ extern __inline__ rt_fix rt_fix_floor(rt_fix fix) { rt_fix fraction = rt_fix_frac(fix); if(0 != fraction._value) { if(fix._value < 0) { fix._value = fix._value - fraction._value - (1 << (RT_FIXWL - fix._iwl)); return fix; } else { fix._value = fix._value - fraction._value; return fix; } } return fix; } /* End of rt_fix_floor */ /* * Calculate the smallest integral value not less than the value of * a given fixed point number. * In: * rt_fix fix the fixed point number to calculate the largest * integral value from. * Out: * A fixed point number which represents the smallest integral * value not less than the value of the called object. */ extern __inline__ rt_fix rt_fix_ceil(rt_fix fix) { rt_fix fraction = rt_fix_frac(fix); if(0 != fraction._value) { if(fix._value < 0) { fix._value = fix._value - fraction._value; return fix; } else { fix._value = fix._value + (1 << (RT_FIXWL - fix._iwl)) - fraction._value; return fix; } } return fix; } /* End of rt_fix_ceil */ /* * Extract signed integral and fractional part of a fixed point number. * In: * rt_fix fix the fixed point number to extract the parts from * InOut: * rt_fix *iptr pointer to a fixed point number in which the integral * part will be stored. * Out: * A fixed point number which represents the fractional part of fix. */ extern __inline__ rt_fix rt_fix_modf(rt_fix fix, rt_fix *iptr) { rt_fix fraction = rt_fix_frac(fix); if(iptr) { iptr->_value = fix._value - fraction._value; iptr->_iwl = fix._iwl; iptr->_errorset = fix._errorset; } return fraction; } /* End of rt_fix_modf */ /* * Round a fixed point number to nearest integral value. * In: * rt_fix fix the fixed point number which is rounded * Out: * A fixed point number which represents the rounded value * of fix. */ extern __inline__ rt_fix rt_fix_round(rt_fix fix) { rt_fix fraction = rt_fix_abs(rt_fix_frac(fix)); fraction._value >>= (RT_FIXWL - fraction._iwl) - 1; if(fix._value >= 0) { if(fraction._value > 0) { return rt_fix_ceil(fix); } else { return rt_fix_floor(fix); } } else { if(fraction._value > 0) { return rt_fix_floor(fix); } else { return rt_fix_ceil(fix); } } } /* End of rt_fix_round */ /* * Calculate the sine of a fixed point number. * In: * rt_fix fix the fixed point number to calculate * the sine from * Pre: * |fix| <= 1024, to get a result with a precision of * approximately 1E-4. * Out: * A fixed point number which represents the approximated * sine of fix. */ extern rt_fix rt_fix_sin(rt_fix fix); /* * Calculate the arc sine of a fixed point number. * In: * rt_fix fix the fixed point number to calculate * the arc sine from * Pre: * fix e [-1, 1]. * Out: * A fixed point number which represents the approximated * arc sine of fix. */ extern rt_fix rt_fix_asin(rt_fix fix); /* * Calculate the cosine of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * cosine from * Pre: * |fix| <= 1024, to get a result with a precision of * approximately 1E-4. * Out: * A fixed point number which represents the approximated * cosine of fix. */ extern rt_fix rt_fix_cos(rt_fix fix); /* * Calculate the arc cosine of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * arc cosine from * Pre: * fix e [-1, 1]. * Out: * A fixed point number which represents the approximated * arc cosine of fix. */ extern rt_fix rt_fix_acos(rt_fix fix); /* * Calculate the tangent of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * arc tangent from * Pre: * |fix| <= 1024, to get a result with a precision of * approximately 1E-4. * Out: * The approximated tangent of the rt_fix number fix. */ extern rt_fix rt_fix_tan(rt_fix fix); /* * Calculate the arc tangent of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * arc tangent from * Out: * A fixed point number which represents the approximated * arc tangent of fix. */ extern rt_fix rt_fix_atan(rt_fix fix); /* * Calculate the square root of a fixed point number. * In: * rt_fix fix the fixed point number to calculate * the square root from * Out: * - A fixed point number which represents the approximated * square root of fix. * - If fix is negative the square root of the absolute value * of fix is calculated. */ extern rt_fix rt_fix_sqrt(rt_fix fix); /* * Calculate fix raised to the power of e. * In: * rt_fix fix the fixed point number to be raised to the * power of e. * Out: * A fixed point number which represents the result of * the calculation. */ extern rt_fix rt_fix_exp(rt_fix fix); /* * Calculate the logarithm to the base of two. * In: * rt_fix fix the fixed point number to calculate * the logarithm to the base of two from. * Out: * - A fixed point number which represents the result of * the calculation. * - If fix is negative the logarithm to the base of two of * the absolute value of fix is calculated. * - If fix is zero rt_fix_min is returned. */ extern rt_fix rt_fix_log2(rt_fix x); /* * Calculate the natural logarithm of fix. * In: * rt_fix fix the fixed point number to calculate * the natural logarithm from. * Out: * - A fixed point number which represents the result of * the calculation. * - If fix is negative the natural logarithm of the * absolute value of fix is calculated. * - If fix is zero rt_fix_min is returned. */ extern __inline__ rt_fix rt_fix_log(rt_fix fix) { rt_fix ln_2 = {1488522236, 0, 0}; /* = 0.69314718 */ return rt_fix_mul(ln_2, rt_fix_log2(fix)); } /* End of rt_fix_log */ /* * Calculate the decimal logarithm of fix. * In: * rt_fix fix the fixed point number to calculate * the decimal logarithm from. * Out: * - A fixed point number which represents the result of * the calculation. * - If fix is negative the logarithm to the base of ten of * the absolute value of fix is calculated. * - If fix is zero rt_fix_min is returned. */ extern __inline__ rt_fix rt_fix_log10(rt_fix fix) { rt_fix log_2 = {646456993, 0, 0}; /* = 0.301029995 */ return rt_fix_mul(log_2, rt_fix_log2(fix)); } /* End of rt_fix_log10 */ /* * Calculate x raised to the power of y. * In: * rt_fix fix the fixed point number to be raised * to the power of y. * rt_fix y the exponent. * Pre: * If y is not an integral value then x must be positive. * Out: * - A fixed point number which represents the result of * the calculation. * - If fix is negative and y is not an integral value then * the absolute value of fix is used to calculate the * result and RT_FIX_UNDEFINED is set in the error set * of the result. */ extern __inline__ rt_fix rt_fix_pow(rt_fix fix, rt_fix y) { if(rt_fix_lss(fix, rt_fix_0) && rt_fix_neq(rt_fix_frac(y), rt_fix_0)) { fix = rt_fix_abs(fix); fix = rt_fix_exp(rt_fix_mul(y, rt_fix_log(fix))); rt_fix_erraddset(&fix, RT_FIX_UNDEFINED); return fix; } return rt_fix_exp(rt_fix_mul(y, rt_fix_log(fix))); } /* End of rt_fix_pow */ /* * Calculate the hyperbolic sine of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * hyperbolic sine from. * Out: * A fixed point number which represents the result of * the calculation. */ extern __inline__ rt_fix rt_fix_sinh(rt_fix fix) { rt_fix one_half = {1073741824, 0, 0}; /* = 0.5 */ return rt_fix_mul(rt_fix_sub(rt_fix_exp(fix), rt_fix_exp(rt_fix_neg(fix))), one_half); } /* End of rt_fix_sinh */ /* * Calculate the hyperbolic cosine of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * hyperbolic cosine from. * Out: * A fixed point number which represents the result of * the calculation. */ extern __inline__ rt_fix rt_fix_cosh(rt_fix fix) { rt_fix one_half = {1073741824, 0, 0}; /* = 0.5 */ return rt_fix_mul(rt_fix_add(rt_fix_exp(fix), rt_fix_exp(rt_fix_neg(fix))), one_half); } /* End of rt_fix_cosh */ /* * Calculate the hyperbolic tangent of a fixed point number. * In: * rt_fix fix the fixed point number to calculate the * hyperbolic tangent from. * Out: * A fixed point number which represents the result of * the calculation. */ extern __inline__ rt_fix rt_fix_tanh(rt_fix fix) { return rt_fix_div(rt_fix_sub(rt_fix_exp(fix), rt_fix_exp(rt_fix_neg(fix))), rt_fix_add(rt_fix_exp(fix), rt_fix_exp(rt_fix_neg(fix)))); } /* End of rt_fix_tanh */ #ifdef RT_FIXMISC /* * assign a fixed point number to another fixed point number without * changing the integer word lenght of the fixed point number * to which is assigned. * InOut: * rt_fix *left pointer to fixed point number which is assigned to * In: * rt_fix right fixed point number which is assigned to left * Pre: * The largest value the fixed point number left can be assigned to * is equal or greater than the fixed point number right. * Post: * The fixed point number left has the same value as the fixed * point number right. The integer word length of the fixed * point number left is not changed. * Out: * 0 on success * 1 on error */ extern short rt_fix_assfix(rt_fix *left, rt_fix right); /* * assign a integer number to a fixed point number without * changing the integer word lenght of the fixed point number * to which is assigned. * InOut: * rt_fix *left pointer to fixed point number which is * assigned to * In: * int i integer number which is assigned to left * Pre: * The largest value the fixed point number left can be assigned to * is equal or greater than i. * Post: * The fixed point number left has the value i. The integer word * length of the fixed point number left is not changed. * Out: * 0 on success * 1 on error (overflow) */ extern short rt_fix_assi(rt_fix *left, int i); /* * assign a long number to a fixed point number without changing * the integer word length of the fixed point number to which * is assigned. * InOut: * rt_fix *left pointer to fixed point number which is * assigned to * In: * long l long number which is assigned to left * Pre: * The largest value the fixed point number left can be assigned to * is equal or greater than l. * Post: * The fixed point number left has the value l. The integer word * length of the fixed point number left is not changed. * Out: * 0 on success * 1 on error (overflow) */ extern short rt_fix_assl(rt_fix *left, long l); #ifndef __KERNEL__ /* * assign a double number to a fixed point number without * changing the integer word length of the fixed point number * to which is assigned. * InOut: * rt_fix *left pointer to fixed point number which is * assigned to * In: * double d double number which is assigned to left * Post: * The number left has the value d. The fraction word length * of the left is not changed. * Out: * 0 on success * 1 on error (overflow) */ extern short rt_fix_assd(rt_fix *left, double d); #endif /* __KERNEL__ */ /* * Set the integer word length of a fixed point number. * InOut: * rt_fix *fix pointer to the fixed point number which * is manipulated * In: * unsigned short iwlen the new integer word length * Post: * The integer word length of the fixed point number is * set to iwlen. * Out: * 0 on success * 1 on error */ extern __inline__ short rt_fix_set_iwl(rt_fix *fix, unsigned short iwlen) { if(!fix) { return 1; } fix->_iwl = iwlen; return 0; } /* End of rt_fix_set_iwl */ /* * query integer word length of a fixed point number. * In: * rt_fix fix the fixed point number to query the * integer word length from * Out: * The integer word length of fix. */ extern __inline__ unsigned short rt_fix_get_iwl(rt_fix fix) { return fix._iwl; } /* End of rt_fix_get_iwl */ /* * query internal representation * In: * rt_fix fix the fixed point number to query the * internal representation from * Out: * The internal representation of fix. */ extern __inline__ long rt_fix_get_rep(rt_fix fix) { return fix._value; } /* End of rt_fix_get_rep */ /* * convert a fixed point number into its string representation. * The string representation has the following format: * internal_value integer-word-length fraction-word-length * = long = int = int * In: * rt_fix fix the fixed point number to print * char *str_rep the string to print the representation * into. * Pre: * str_rep is not NULL and its length is equal or greater than * RT_FIX_STR_REP_SIZE. * Post: * str_rep contains the string representation of the fixed point * number fix. * Out: * 0 on success * 1 on error */ extern short rt_fix_toa(rt_fix fix, char *str_rep); /* * convert a given string representation of a fixed point number into * a fixed point number. * In: * const char *str_rep the string representation of a fixed point * number. * rt_fix *result the fixed point number to store the result of * the conversion into. * Pre: * str_rep and result are not NULL and str_rep contains a valid string * representation of a fixed point number. * Post: * The fixed point number *result contains the fixed point number * described by string str_rep. * Out: * 0 on success * 1 on error */ extern short rt_fix_atofix(rt_fix *result, const char *string_rep); #endif /* RT_FIXMISC */ #line 1688 "rt_fix.nw" #endif /* _RT_FIX_H_ */