Project | Q: Fixed Point Number Library |
---|---|
Author | Richard James Howe |
Copyright | 2018 Richard James Howe |
License | MIT |
howe.r.j.89@gmail.com | |
Website | https://github.com/howerj/q |
This is a small fixed point number library designed for embedded use. It implements all of your favorite transcendental functions, plus only the best basic operators, selected for your calculating pleasure. The format is a signed Q16.16, which is good enough for Doom and good enough for you.
The default makefile target builds the library and a test program, which will require a C compiler (and Make). The library is small enough that is can be easily modified to suite your purpose. The dependencies are minimal; they are few string handling functions, and 'tolower' for numeric input. This should allow the code to ported to the platform of your choice. The 'run' make target builds the test program (called 'q') and runs it on some input. The '-h' option will spit out a more detailed help.
The trigonometric functions, and some others, are implemented internally with CORDIC.
Of note, all operators are bounded by minimum and maximum values, which are not shown in the following table, by default all arithmetic is saturating. The effective input range of a number might lower than what is possible given a mathematical functions definition - either because of the limited range of the Q16.16 type, or because the implementation of a function introduces too much error along some part of its' input range. Caveat Emptor (although you're not exactly paying for this library now, are you? Caveat Auditor perhaps).
( This table needs completing, specifically the input ranges... )
C Function | Operator | Input Range | Asserts | Notes |
---|---|---|---|---|
qadd(a, b) | a + b | Addition | ||
qsub(a, b) | a - b | Subtraction | ||
qdiv(a, b) | a / b | b != 0 | Yes | Division |
qmul(a, b) | a * b | Multiplication | ||
qrem(a, b) | a rem b | b != 0 | Yes | Remainder |
qsin(theta) | sin(theta) | Sine | ||
qcos(theta) | cos(theta) | Cosine | ||
qtan(theta) | tan(theta) | Tangent | ||
qcot(theta) | cot(theta) | Cotangent | ||
qhypot(a, b) | hypot(a, b) | Hypotenuse; sqrt(a*a + b*b) | ||
qatan(t) | atan(t) | Arctangent | ||
qsinh(a) | sinh(a) | Hyperbolic Sine | ||
qcosh(a) | cosh(a) | Hyperbolic Cosine | ||
qtanh(a) | tanh(a) | Hyperbolic Tangent | ||
qexp(e) | exp(e) | e < ln(MAX) | No | Exponential function, High error for 'e' > ~7. |
qlog(n) | log(n) | n > 0 | Yes | Natural Logarithm |
qsqrt(x) | sqrt(x) | n >= 0 | Yes | Square Root |
qround(q) | round(q) | Round to nearest value | ||
qceil(q) | ceil(q) | Round up value | ||
qtrunc(q) | trunc(q) | Truncate value | ||
qfloor(q) | floor(q) | Round down value | ||
qnegate(a) | -a | Negate a number | ||
qabs(a) | abs(a) | Absolute value of a number | ||
qfma(a, b, c) | (a*b)+c | Fused Multiply Add, uses Q32.32 internally | ||
qequal(a, b) | a == b | |||
qsignum(a) | signum(a) | Signum function | ||
qsign(a) | sgn(a) | Sign function | ||
For the round/ceil/trunc/floor functions the following table from the cplusplus.com helps:
value | round | floor | ceil | trunc |
---|---|---|---|---|
2.3 | 2.0 | 2.0 | 3.0 | 2.0 |
3.8 | 4.0 | 3.0 | 4.0 | 3.0 |
5.5 | 6.0 | 5.0 | 6.0 | 5.0 |
-2.3 | -2.0 | -3.0 | -2.0 | -2.0 |
-3.8 | -4.0 | -4.0 | -3.0 | -3.0 |
-5.5 | -6.0 | -6.0 | -5.0 | -5.0 |
Have fun with the adding, and subtracting, and stuff, I hope it goes well.
- Update this To Do section with comments from around the project
- Look into, or implement a BKM version for computing elementary functions
instead of using a CORDIC core. See also:
- https://www-almasty.lip6.fr/~bajard/MesPublis/Spie1999.pdf
- http://perso.ens-lyon.fr/jean-michel.muller/BKM94.pdf A hardware implementation for an FPGA in VHDL would also be an interesting project.
- Investigate using part of the numbers range to represent NaN (Not A Number), and +/- Infinity, including number conversion to/from those special numbers.
- A 64-bit version would be nice, for Q32.32 numbers.