Skip to content

Commit

Permalink
Add fixed point math library (#316)
Browse files Browse the repository at this point in the history
* Add fixed point math library

* Use union and bitfield for storage type

Address many of the review comments as well

* Expand fixed point library to add better handling for int types and promotion and also add multiplication

* Add newline

* Finish change; rework slightly

- Like C integers, silently truncate on implicit conversion to a smaller
  type.
- Compound assignments convert to the join type above then truncate, as
  C integers do.

* Fix example

* Minor refactor

* Some fixes

---------

Co-authored-by: Daniel Thornburgh <[email protected]>
  • Loading branch information
jroweboy and mysterymath authored Mar 22, 2024
1 parent 450982a commit 47b35b2
Show file tree
Hide file tree
Showing 3 changed files with 640 additions and 0 deletions.
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ endfunction()
add_executable(minimal minimal.c)
install_example(minimal)
if(HOSTED)
add_executable(fixed-point fixed-point.cc)
install_example(fixed-point)
add_executable(hello-getchar hello-getchar.c)
install_example(hello-getchar)
add_executable(hello-malloc hello-malloc.c)
Expand Down
62 changes: 62 additions & 0 deletions examples/fixed-point.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#undef NDEBUG
#include <assert.h>
#include <fixed_point.h>

// This file is an example of how to use the high level fixed point
// library in fixed_point.h. The fixedpoint::Value class provides a
// typesafe wrapper for fixed point mathematical operations and
// convenience methods for accessing the integral and decimal parts.

int main() {
// Creates a signed fixed point number with 100 as the integral part
// The full representation of the number is 0x6400 where 0x64 is the
// integer part and 0x00 is the fractional part.
FixedPoint<8, 8> basic_number{100};

// Math operators work out of the box
// This will add 19 to the integral part
basic_number += 19;

// Integer and fractional parts can be accessed individually
assert( basic_number.as_i() == 119 );

// Now for the fun part, here's a second number but with a fractional part
// This number in hexadecimal is 0x0110
FixedPoint<8, 8> second_number{1, 16};

// Subtraction works as well.
basic_number -= second_number;
// The new basic_number integral part is now 117 (since we subtracted a fraction part)
assert( basic_number.as_i() == 117 );
// The fractional part is
assert( basic_number.as_f() == 0xf0 );

// Now that the basics are out of the way, let's start using the helper methods
// in the literals namespace
using namespace fixedpoint_literals;

// For the common 8.8 and 12.4 fixed point numbers, user defined literals are
// provided for converting from floating point numbers at compile time.
// This converts 9.87 into an 12.4 number (0x009e)
auto third_number = 9.87_12_4;

// Comparisons work between fixed point numbers or integer numbers
// Additionally fixed point numbers will be converted to other fixed point
// numbers automatically when performing math operations.
assert(third_number + second_number <= basic_number);
assert(basic_number < 119);

// fixed point numbers can be signed or unsigned as well with the optional
// third parameter. They are signed by default like other integer types
// There is also a matching literal type for unsigned numbers `_u8_8`
// as well as an explicit signed version `_s8_8`
fu8_8 unsigned_number = 40.4_u8_8;
// The type is not required of course, the following also works.
auto unsigned_number2 = 40.4_u8_8;

unsigned_number += 200;
// Since its unsigned, it will be treated as a positive value instead
assert ( unsigned_number > 200 );

return 0;
}
Loading

0 comments on commit 47b35b2

Please sign in to comment.