Skip to content

Instantly share code, notes, and snippets.

@msullivan
Last active August 29, 2015 13:58
Show Gist options
  • Save msullivan/9944197 to your computer and use it in GitHub Desktop.
Save msullivan/9944197 to your computer and use it in GitHub Desktop.
Silly fixed point number macros
typedef int fixed_t;
#define SIGN(n) ((n) < 0 ? -1 : 1)
#define FRACTIONAL_BITS 24 // Number of fixed point fractional bits
// A bunch of macros for constructing fixed point numbers.
#define INT_TO_FIXED(n) ((n) << FRACTIONAL_BITS)
#define FRAC_TO_FIXED(n, d) ((fixed_t)(INT_TO_FIXED((long long)(n)) / (d)))
#define IMPROPER_TO_FIXED(i, n, d) FRAC_TO_FIXED((i)*(d) + SIGN(i)*(n), (d))
// Count the digits in a literal through preprocessor badness
#define DIGITS(n) (sizeof(#n)-1)
// Computes an integer power using exponentiation by squaring.
// Only looks at the bottom 5 bits because exponents greater than 32 overflow.
// Reevaluates its arguments like a bajillion times. Is hueg like xbox.
#define IPOW1(x, n) ((n)&1 ? (x) : 1)
#define IPOW2(x, n) (((n)&1 ? (x) : 1) * IPOW1((x)*(x), (n) >> 1))
#define IPOW3(x, n) (((n)&1 ? (x) : 1) * IPOW2((x)*(x), (n) >> 1))
#define IPOW4(x, n) (((n)&1 ? (x) : 1) * IPOW3((x)*(x), (n) >> 1))
#define IPOW5(x, n) (((n)&1 ? (x) : 1) * IPOW4((x)*(x), (n) >> 1))
#define IPOW IPOW5
#define POW10(i) IPOW(10, (i))
// Force a constant to be interpreted as a decimal number.
// That is, FORCE_DECIMAL(050) is 50, not 40.
#define FORCE_DECIMAL(n) ((1 ## n) - POW10(DIGITS(n)))
#define DEC_TO_FIXED(i, dec) \
IMPROPER_TO_FIXED(i, FORCE_DECIMAL(dec), POW10(DIGITS(dec)))
// Now we can write constants like:
// DEC_TO_FIXED(3,1415), DEC_TO_FIXED(-1,5), DEC_TO_FIXED(0,09)
// and have it produce the proper fixed point numbers.
// All of the stuff can be evaluated at compile time, too,
// so they should be usable when constants are needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment