Up: Sokrates Home-Page Previous: rt_linux

OBJECT rt_fix IS PASSIVE

DESCRIPTION
This module implements fixed point arithmetic for rt-linux. This code is inspired by:

In contrast to the fixed point implementations mentioned above the functionality supplied by this module follows different goals. These goals are:
Thus a shared library called librt_fix.so and a kernel module called rt_fix.o are supplied.

The base type for a fixed point number is called rt_fix and contains a 32-bit word used to represent the fixed point number. The length of the integral part and of the fractional part of the fixed point number is determined when a variable of type rt_fix is initialized. The internal representation is always kept left aligned and only as many bits as needed are used for the integral part. This aims to keeping as much precision for the fractional part as possible.

The following example show the layout of a fixed point number with 17-bits for the integral part, 14-bits for the fractional part and one sign-bit.

Layout of a fixed-point number with one Sign-Bit,
 18 Bits for the integral and 14 Bits for the fractional part


This means that the following numeric limits are given for the integral part:
The accuracy of the fixed point number is 2-14 which is four digits after the decimal point.

The goal of using fixed point arithmetic is to avoid bothering with the FPU in kernel space. This seems reasonable, because using the FPU in kernel space is a constant source of trouble. The drawback is the limited accuracy of and programming overhead caused by fixed point arithmetic.

Doubles used in user space can be converted to fixed point numbers before sending them to rtlinux (and thus to kernel space) and in kernel space calculations should be done using fixed point arithmetic. If in a overflow in a called function occurs the overflowed fixed point number gets saturated and if a overflow handler is installed this handler is called. The same procedure takes place in case of an attempt to divide by zero. In this case a divide by zero handler is called and the result is saturated, too.

It is planned to implement the functions shown in the table below (a + in the status column means available and - means not available):

Name C-equivalent Description State
rt_fix_div() / operator calculates a / b +
rt_fix_mul() * operator calculates a * b +
rt_fix_add() + operator calculates a + b +
rt_fix_sub() - operator calculates a - b +
rt_fix_toi() cast operator converts a rt_fix variable into a integer number. +
rt_fix_init_i() none initialize a rt_fix variable with a integer value. +
rt_fix_tod() cast operator converts a rt_fix variable into a double number. +
rt_fix_init_d() none initialize a rt_fix variable with a double number. +
rt_fix_frac() none extracts the fractional part from a rt_fix variable. +
rt_fix_ceil() ceil() extract smallest integral fixed point variable not less than given rt_fix variable. +
rt_fix_floor() floor() extract largest integral fixed point variable not greater than given rt_fix variable. +
rt_fix_modf() modf() extracts signed integral and fractional part from a rt_fix variable. +
rt_fix_abs() abs() computes the absolute value of a rt_fix variable. +
rt_fix_sin() sin() sine function. +
rt_fix_asin() asin() arc sine function. +
rt_fix_cos() cos() cosine function. +
rt_fix_acos() acos() arc cosine function. +
rt_fix_tan() tan() tangent function. +
rt_fix_atan() atan() arc tangent function. -
rt_fix_atan2() atan2() arc tangent function of two variables. -
rt_fix_ldexp() ldexp() multiply given rt_fix variable by integral power of 2. +
rt_fix_sqrt() sqrt() square root. +
rt_fix_pow() pow() x raised to the power of y. -
rt_fix_log() log() natural logarithm of a given rt_fix number. -
rt_fix_log10() log10() base-10 logarithm of a given rt_fix number. -
rt_fix_exp() exp() e to the power of given rt_fix number. +
rt_fix_sinh() sinh() hyperbolic sine function. -
rt_fix_cosh() cosh() hyperbolic cosine function. -
rt_fix_tanh() tanh() hyperbolic tangent function. -

IMPLEMENTATION CONSTRAINTS
The multiplication function rt_fix_mul and the division function rt_fix_div are implemented using inline assembly language. The functions rt_fix_tod and rt_fix_tof are not available in kernel space.

PROVIDED
#ifndef _RT_FIX_H_
#define _RT_FIX_H_
/*
* Fixed Point Arithmetic Routines
*
* 1998 Till Christian Siering
*
*/


PROVIDED TYPES
typedef struct _rt_fix {
char _string_rep[100];
long _value; /* value of this number */
unsigned int _iwl; /* integer word-length => bits for the mantissa */
unsigned int _fwl; /* fractional word-length => bits for the exponent */
void (*_overflow_handler)(void);
void (*_divzero_handler)(void);
} rt_fix;

/*
* initialize a fixed point variable with default values.
* InOut:
* rt_fix *fix point to the fixed point variable which
* is manipulated
* Post:
* The fixed point variable fix is set to 0 and its
* integer word length is set to DEFAULT_IWL.
*/
extern int rt_fix_init(rt_fix *fix);

/*
* initialize a fixed point variable with a given integer.
* InOut:
* rt_fix *fix point to the fixed point variable which
* is initialized
* In:
* int i the integer used for initialization
* Out:
* 0 on success
* 1 on error
* Post:
* The fixed point variable fix is initialized with the
* given integer.
*/
extern int rt_fix_init_i(rt_fix *fix, int i);

/*
* initialize a fixed point variable with a given long.
* InOut:
* rt_fix *fix point to the fixed point variable which
* is initialized
* In:
* int l the long used for initialization
* Out:
* 0 on success
* 1 on error
* Post:
* The fixed point variable fix is initialized with the
* given long.
*/
extern int rt_fix_init_l(rt_fix *fix, long l);

/*
* initialize with given 32-Bit-Mask and given integer word length.
* InOut:
* rt_fix *fix point to the fixed point variable which
* is initialized
* In:
* long bit_mask the bit_mask used for initialization
* int iwlen the integer word length used for initialization
* Out:
* 0 on success
* 1 on error
* Post:
* The fixed point variable fix is initialized with the
* given bit mask and the given integer word length.
*/
extern int rt_fix_init_mask(rt_fix *fix, long bit_mask, unsigned int iwlen);

#ifndef __KERNEL__
/*
* construct from a double value
*/
extern int rt_fix_init_d(rt_fix *fix, double d);
#endif

/*
* destroy rt_fix variable.
*/
extern void rt_fix_delete(rt_fix *fix);

/*
* transform a fixed point variable to long.
* In:
* rt_fix fix the fixed point variable to be
* transformed
* Out:
* The result of the transformation.
*/
extern long rt_fix_tol(rt_fix fix);

/*
* transform a fixed point variable to a int.
* In:
* rt_fix fix the fixed point variable to be
* transformed
* Out:
* The result of the transformation.
*/
extern int rt_fix_toi(rt_fix fix);

#ifndef __KERNEL__
/*
* transform a fixed point variable to a double.
* In:
* rt_fix fix the fixed point variable to be
* transformed
* Out:
* The result of the transformation.
*/
extern double rt_fix_tod(rt_fix fix);
#endif

/*
* assign a fixed point variable to another fixed point variable.
* InOut:
* rt_fix *left pointer to fixed point variable which is assigned to
* In:
* rt_fix right fixed point variable which is assigned to left
* Post:
* The variable left has the same value as the variable right.
* The fraction word length of the left is not changed.
*/
extern int rt_fix_assfix(rt_fix *left, rt_fix right);

/*
* assign a integer variable to a fixed point variable.
* InOut:
* rt_fix *left pointer to fixed point variable which is
* assigned to
* In:
* int i integer variable which is assigned to left
* Out:
* 0 on success
* 1 on error (overflow)
* Post:
* The variable left has the value i. The fraction word length
* of the left is not changed.
*/
extern int rt_fix_assi(rt_fix *left, int i);

/*
* assign a long variable to a fixed point variable.
* InOut:
* rt_fix *left pointer to fixed point variable which is
* assigned to
* In:
* long l long variable which is assigned to left
* Out:
* 0 on success
* 1 on error (overflow)
* Post:
* The variable left has the value l. The fraction word length
* of the left is not changed.
*/
extern int rt_fix_assl(rt_fix *left, long l);

#ifndef __KERNEL__
/*
* assign a double variable to a fixed point variable.
* InOut:
* rt_fix *left pointer to fixed point variable which is
* assigned to
* In:
* double d double variable which is assigned to left
* Out:
* 0 on success
* 1 on error (overflow)
* Post:
* The variable left has the value d. The fraction word length
* of the left is not changed.
*/
extern int rt_fix_assd(rt_fix *left, double d);
#endif

/*
* shift a fixed point variable b bits left.
* In:
* rt_fix arg the fixed point number to be shifted
* int b the number of bits x is shifted.
* Pre:
* The sum of the integer word length of arg and b is
* smaller or equal RT_FIXWL.
* Out:
* On success fixed point number containing:
* value(result) = value(arg)
* iwl(result) = iwl(arg) + b
* fwl(result) = fwl(arg) - b
* On error rt_fix_max.
*/
extern rt_fix rt_fix_shl(rt_fix arg, int b);

/*
* shift a fixed point variable b bits right.
* In:
* rt_fix arg the fixed point number to be shifted
* int b the number of bits x is shifted.
* Pre:
* The sum of the fractional word length of arg and b
* is smaller or equal RT_FIXWL.
* Out:
* On success fixed point number containing:
* value(result) = value(arg)
* iwl(result) = iwl(arg) - b
* fwl(result) = fwl(arg) + b
* On error rt_fix_min.
*/
extern rt_fix rt_fix_shr(rt_fix arg, int b);

/*
* Add to fixed point variables.
* 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.
* The integer word length of the result is minimal.
*/
extern rt_fix rt_fix_add(rt_fix x, rt_fix y);

/*
* Subtract to fixed point variables.
* In:
* rt_fix x the minuend
* rt_fix y the subtrahend
* Out:
* A fixed point number representing the result of x - y.
* The integer word length of the result is minimal.
*/
extern rt_fix rt_fix_sub(rt_fix x, rt_fix y);

/*
* Multiply two fixed point variables.
* In:
* rt_fix x the multiplicand
* rt_fix y the multiplicator
* Out:
* A fixed point number representing the result of x * y.
* The integer word length of the result is minimal.
*/
extern rt_fix rt_fix_mul(rt_fix x, rt_fix y);

/*
* Divide two fixed point variables.
* In:
* rt_fix x the divident
* rt_fix y the divisor
* Out:
* A fixed point number representing the result of x / y.
* The integer word length of the result is minimal
*/
extern rt_fix rt_fix_div(rt_fix x, rt_fix y);

/*
* Test if two fixed point variables are equal.
* In:
* rt_fix x a fixed point number
* rt_fix y a fixed point number
* Out:
* 1 if the x and y do not represent the same value
* 0 otherwise
*/
extern int rt_fix_eq(rt_fix x, rt_fix y);

/*
* Test if two fixed point variables are not equal.
* In:
* rt_fix x a fixed point number
* rt_fix y a fixed point number
* Out:
* 1 if the x and y do not represent the same value
* 0 otherwise
*/
extern int rt_fix_neq(rt_fix x, rt_fix y);

/*
* Test if two fixed point variables are greater-equal.
* In:
* rt_fix x a fixed point number
* rt_fix y a fixed point number
* Out:
* 1 if the value x represents is greater or equal y
* 0 otherwise
*/
extern int rt_fix_geq(rt_fix x, rt_fix y);

/*
* Test if two fixed point variables are smaller-equal.
* In:
* rt_fix x a fixed point number
* rt_fix y a fixed point number
* Out:
* 1 if the value x represents is smaller or equal y
* 0 otherwise
*/
extern int rt_fix_leq(rt_fix x, rt_fix y);

/*
* Test if one fixed point variables is greater than another.
* In:
* rt_fix x a fixed point number
* rt_fix y a fixed point number
* Out:
* 1 if the value x represents is greater y
* 0 otherwise
*/
extern int rt_fix_gt(rt_fix x, rt_fix y);

/*
* Test if one fixed point variables is smaller than another.
* In:
* rt_fix x a fixed point number
* rt_fix y a fixed point number
* Out:
* 1 if the value x represents is smaller y
* 0 otherwise
*/
extern int rt_fix_lt(rt_fix x, rt_fix y);

/*
* Set the integer word length of a fixed point variable.
* InOut:
* rt_fix *fix pointer to the fixed point variable which
* is manipulated
* In:
* unsigned int iwlen the new integer word length
* Out:
* 0 on success
* 1 on error
* Post:
* The integer word length of the fixed variable is set
* to iwlen and the fraction word length is set to
* RT_FIXWL - iwlen.
*/
extern int rt_fix_set_iwl(rt_fix *fix, unsigned int iwlen);

/*
* Set the fraction word length of a fixed point variable.
* InOut:
* rt_fix *fix pointer to the fixed point variable which
* is manipulated
* In:
* unsigned int fwlen the new fraction word length
* Post:
* The fraction word length of the fixed point variable is
* set to fwlen and the integer word length is set to
* RT_FIXWL - fwlen.
*/
extern int rt_fix_set_fwl(rt_fix *fix, unsigned int fwlen);

/*
* query fraction word length of a fixed point variable.
* In:
* rt_fix fix the fixed point number to query the fraction
* word length from
* Out:
* The fraction word length of fix.
*/
extern int rt_fix_get_fwl(rt_fix fix);

/*
* query integer word length of a fixed point variable.
* In:
* rt_fix fix the fixed point number to query the integer
* word length from
* Out:
* The integer word length of fix.
*/
extern int rt_fix_get_iwl(rt_fix fix);

/*
* query internal representation
* In:
* rt_fix fix the fixed point number to query the
* internal representation from
* Out:
* The internal representation of fix.
*/
extern long rt_fix_get_rep(rt_fix fix);

/*
* query string representation which is a string with the
* following format:
* internal_value integer-word-length fraction-word-length
* = long = int = int
* Out:
* The string representation of this fixed point object.
*/
extern char *rt_fix_toa(rt_fix fix);

/*
* set this fixed point number to a given string representation.
* In:
* const char *string_rep the string representation
* Out:
* 0 on success
* 1 on error
* Post:
* The called fixed point object is set to the described
* fixed point number described in the string representation.
*/
extern int rt_fix_atofix(rt_fix *result, const char *string_rep);

/************************
* 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:
* The result of the multiplication.
*/
extern rt_fix rt_fix_ldexp(rt_fix fix, int pow2);

/*
* Get the fractional part of a fixed point number.
* In:
* rt_fix fix fixed point to extract the fractional part
* from.
* Out:
* A fixed point number which contains the fractional part
* of fix.
*/
extern rt_fix rt_fix_frac(rt_fix fix);

/*
* Calculate the largest integral value of a fixed point variable
* not greater than the value fixed point variable itself.
* In:
* rt_fix fix the fixed point variable 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 rt_fix rt_fix_floor(rt_fix fix);

/*
* Calculate smallest integral value not less than the value of
* the a given fixed point number.
* In:
* rt_fix fix the fixed point variable 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 rt_fix rt_fix_ceil(rt_fix fix);

/*
* Computes the absolute value of x.
* Out:
* The absolute value of x.
*/
extern rt_fix rt_fix_abs(rt_fix fix);

/*
* Extract signed integral and fractional part of a fixed point variable.
* In:
* rt_fix fix the fixed point variable to extract the parts from
* InOut:
* rt_fix *iptr pointer to a fixed point variable in which the integral
* part will be stored.
* Out:
* A fixed point number which represents the fractional part of fix.
*/
extern rt_fix rt_fix_modf(rt_fix fix, rt_fix *iptr);

/*
* Round a fixed point variable to nearest integral value.
* In:
* rt_fix fix the fixed point variable which is rounded
* Out:
* A fixed point number which represents the rounded value
* of fix.
*/
extern rt_fix rt_fix_round(rt_fix fix);

/*
* Calculate the sine of a fixed point variable.
* In:
* rt_fix fix the fixed point variable to calculate
* the sine from
* 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 sine from
* 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
* Out:
* A fixed point number which represents the approximated
* cosine of fix.
*/
extern rt_fix rt_fix_cos(rt_fix arg);

/*
* Calculate the arc cosine of a fixed point number.
* In:
* rt_fix fix the fixed point number to calculate the
* arc cosine from
* Out:
* A fixed point number which represents the approximated
* arc cosine of fix.
*/
extern rt_fix rt_fix_acos(rt_fix arg);

/*
* Calculate the tangent of a fixed point number.
* Out:
* The approximated tangent of the rt_fix number x.
*/
extern rt_fix rt_fix_tan(rt_fix arg);

/*
* Calculate the square root of a fixed point variable.
* In:
* rt_fix fix the fixed point to calculat the square root
* from
* Out:
* A fixed point number which represents the approximated
* square root of fix.
*/
extern rt_fix rt_fix_sqrt(rt_fix arg);

/*
* Calculate the 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 representes the result of
* the calculation.
*/
extern rt_fix rt_fix_exp(rt_fix x);

/*
* Set handler which get's triggered, if an overflow occurs.
* Post:
* The given overflow handler will be trigger each time an
* overflow occurrs.
*/
extern void set_overflow_handler(rt_fix *fix, void(*overflow_handler)(void));

/*
* Set handler which get's triggered, if an attempt to divide
* by zero occurs.
* Post:
* The given divide by zero handler will be triggered each time
* an attempt to divide by zero occurs.
*/
extern void set_divzero_handler(rt_fix *fix, void(*divzero_handler)(void));

#endif /* _RT_FIX_H_ */


Till Christian Siering
3/3/1998