Skip to content

Instantly share code, notes, and snippets.

@johnmcfarlane
Last active May 24, 2017 00:46
Show Gist options
  • Save johnmcfarlane/3123b5cfbf27f82d47bfabae6a33dcb9 to your computer and use it in GitHub Desktop.
Save johnmcfarlane/3123b5cfbf27f82d47bfabae6a33dcb9 to your computer and use it in GitHub Desktop.
example of zero-cost abstraction using the fixed_point library
// Signed 15:16 Fixed-Point Square Function Using sg14::elastic
// Here's how to use the fixed_point library on Godbolt.org.
// Normally, you'd just add `#include <sg14/fixed_point>`.
#define SG14_GODBOLT_ORG
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/config.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/config.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/cstdint>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/limits>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/type_traits>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/common.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_type.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_arithmetic.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_make.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_named.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_common_type.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_operators.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/bits/fixed_point_extras.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/auxiliary/elastic_integer.h>
#include <https://raw.githubusercontent.com/johnmcfarlane/fixed_point/develop/include/sg14/auxiliary/elastic.h>
using namespace sg14;
// average two nunbers using 15:16 fixed-point arithmetic
// without using a fixed-point library
float average_int(float input1, float input2) {
// user must scale values by the correct amount
auto fixed1 = static_cast<int32_t>(input1 * 65536.f);
auto fixed2 = static_cast<int32_t>(input2 * 65536.f);
// user must remember to widen the result to avoid overflow
auto sum = int64_t{fixed1} + fixed2;
// at least division is simple
auto avg = sum / 2;
// user must return value to the original scale
return avg / 65536.f;
}
// the same function using sg14::elastic_integer
float average_elastic_integer(float input1, float input2) {
auto fixed1 = elastic_integer<31>{input1 * 65536.f};
auto fixed2 = elastic_integer<31>{input2 * 65536.f};
// elastic_integer automatically widens the result
auto sum = fixed1 + fixed2;
// showing off: to store 2, you only need a 2-bit integer
auto avg = sum / elastic_integer<2>{2};
// but the user must still do all the scaling themselves
return static_cast<float>(avg) / 65536.f;
}
// the same function using sg14::fixed_point
float average_fixed_point(float input1, float input2) {
// fixed_point handles scaling
auto fixed1 = fixed_point<int32_t, -16>{input1};
auto fixed2 = fixed_point<int32_t, -16>{input2};
// but it uses int under the hood; user must still widen
auto sum = fixed_point<int64_t, -16>{fixed1} + fixed2;
// specal function 'divide' is used when we
// want to perform integer division on a real number
auto avg = divide(sum, 2);
return static_cast<float>(avg);
}
// finally, the composition of fixed_point and elastic_integer
float average_elastic(float input1, float input2) {
// alias to fixed_point<elastic_integer<31, int>, -16>
auto elastic1 = elastic<15, 16>{input1};
auto elastic2 = elastic<15, 16>{input2};
// concise, safe and zero-cost!
auto sum = elastic1 + elastic2;
auto avg = sum / elastic<2>{2};
return static_cast<float>(avg);
}
@bryceschober
Copy link

bryceschober commented May 24, 2017

Hmm... this doesn't work for me, even after fixing line 20 to include elastic_fixed_point.h instead of elastic.h: https://godbolt.org/g/N04hY7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment