/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss or reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

/** @addtogroup fixp

Fixpoint can be used as a fast approximation to float point.

These functions can come handy in signal processing and control applications
where you use fixpoint format data. Using fixpoint data needs a little getting
used to it, but if you keep a good track of your radix point at all times,
the fact that you use integer arithmetics instead of float one can save a lot
of computing time. Naturally, your precision is not as high as by using
doubles and the range of values you can represent is severely restricted,
but usually so is your input and output and as long as you keep an eye on
the magnitude of intermediate results, there will not be any problems.

If you are not familiar with fixpoint numbers, here is an extremely brief
introduction. The idea is that you use integer numbers but you treat them
as if they were composed of a whole part and a fractional part. An integer
number, like 123 is actually the number 123.000... Nothing stops you to
imagine that you move the decimal point to the left by two digits, so when
a computation delivers the integer result of 123 you imagine that it
actually means 1.23, by "moving" the radix point to the left. Usually the
notation one uses is i.f where i is the number of bits that are treated as
the integer part of the number and f is the number of bits that are treated
as the fractional part of the number. The sum of i and f is the actual word
length. Thus, if you use 4.28 format it means that the top 4 bits of the
32-bit word represent the integer part, the bottom 28 bits are the fractional
part. In that format 1.0 corresponds to the binary value of 0x10000000 while
0.75 would be 0x0c000000.

As long as your operations are all linear, the position of the radix point
is irrelevant. The binary result will be the same regardless of where you
imagine the radix point to be. 56+67=123 while 5.6+6.7=12.3, it doesn't
matter that you imagined that the decimal point is moved by one digit to
the left. No matter how much you move the radix point, it will always work.
However, for nonlinear operations that is no longer true. Consider that
56*67=3752 (radix point is after the last digit) but of course, if you move
the radix point to the left by one digit in the multiplicands you get
5.6*6.7=32.52, and as you can see the radix point of the result is not at
the same place as in the multiplcands. That's where you have to be very
careful. There are some nonlinear operators where you can move the radix
point in the input and easily work out the new position of the radix point
of the  output. When you multiply, every time you move the radix 1 bit to the
left on the inputs, you will have a result that has its radix point moved by
two positions.
With square root it is the opposite, moving the radix point of the argument
by two places will make the radix point of the result to move by 1 place.
The radix point of division remains unmoved when you move the radix of the
numerator and the denominator by the same amount. There are nonlinear operators,
such as the trigonometric functions, where the position of the radix point
simply can not be changed. In that case, if you have an argument that is
not in the correct format, you have to shift it before passing to the function
so that the radix point is at the position where the function expects it.
Similarly, you may have to shift the result of such a function to match your
preferred radix position. For example, if you have say a sine function that
expects a 4.28 input (in radians) and generates the result in the same
format, but you otherwise use 2.30 format, then you have to shift you
argument to the right by two bits before passing to the function and then
shift the result to the left by two bits.

Unlike working with float-point numbers, the fixpoint format requires you
to keep track of the radix point at each step. In addition, since your
range is limited (in 4.28 signed format the largest number you can represent
is 7.999...) you also have to be vigilant about possible overflow conditions.
You have to make sure that no partial result is ever outside of the allowed
range. This is of course true for all integer calculations as well, but while
a 32-bit integer when procesing 8 or 10 bit data provides ample space for the
extra bits, when you have maybe 3 or 4 integer bits, you can't just add,
say, four numbers together and then divide the result by 4 to calculate their
average, because adding the 4 numbers needs 2 extra bits on the left which
you may not have. An other thing you have to consider is precision. If you
divide a float point number by a power of 2, its precision will not change.
It is because multiplication or division by a power of 2 does not touch the
mantissa of the number, only its exponent. Your mantissa will contain the
same number of significant bits as before.
However, the equivalent operation on a fixpoint number is shifting to the
right for division or to the left for multiplication. Shifting a fixpont
number to the left can easily cause overflow, as detailed above. On the
other hand, shifting a fixpoint number to the right will lose bits and
thus precision. Therefore, you have to keep an eye on the precision angle of
things as well.
<br><br>
Nevertheless, if you are willing to put in the effort, in exchange
you will get functionality that normally requires float point
calculations while using simple integer arithmetic. The speed increase
can be quite significant. Consider that fixpoint addition is actually an
integer addition, a single machine instruction executing in 1 clock while
a \p float add takes about 60 clock cycles. This is, of course, the most
extreme example but addition is easily the most frequent operation.
Multiplication, probably the second most frequent operation, is about 3
times faster for fixpoint operations than for \p floats, not as stark a
contrast as with addition but still a significant advantage.

This collection of functions in the library provides you basic fixed-point
functionality. These routines are written in assembly, therefore they run in
the same time regardless of whether you compile for the ARM or the THUMB
instruction set.

To use these functions you have to include <b>fixpoint.h</b>.

The table below gives you an indication of their performance. The
execution times were measured on an LPC23xx chip running at 60MHz.

@verbatim
     vrot32() 8.4 µs           log32() 7.9 µs
     vabs32() 8.2 µs           exp32() 6.6 µs
     sqrt32() 3.5 µs           rec32() 2.5 µs
     mac32()  0.5 µs
@endverbatim
<br>

An other operation  quite often used in signal processing is the Fourier
transform. The library contains both complex and real valued transforms
and their inverses, using either 32 or 16 bit datum. The Fourier routines
are all written in assembly, thus the execution speed does not depend on
whether you compile for ARM or THUMB.
The following table gives you an idea about the execution time for various
transform sizes, using 32-bit transform. The 16-bit versions are approximately
10% faster. The times were measured on an LPC23xx running at 60MHz.

@verbatim
       Fourier transform execution time for various N-s, [ms]

     Transform         N = 16    32    64   128   256   512  1024
-----------------------------------------------------------------
2N real <-> N cplx       0.07  0.16  0.34  0.75  1.63  3.52  7.57
 N cplx <-> N cplx       0.06  0.14  0.30  0.67  1.47  3.19  6.90
@endverbatim

*/

