Skip to content

Instantly share code, notes, and snippets.

@jido
Created January 11, 2020 21:31
Show Gist options
  • Save jido/23734360e3848ed0f4d8cbaace8f7f95 to your computer and use it in GitHub Desktop.
Save jido/23734360e3848ed0f4d8cbaace8f7f95 to your computer and use it in GitHub Desktop.
Macro to build a Posit at compile time
#ifndef positmacros_h
#define positmacros_h
#ifdef __cplusplus
extern "C"{
#endif
#include <stdint.h>
#define INT8_MASK 0x7f
#define INT16_MASK 0x7fFF
#define INT32_MASK 0x7fFFffFF
#define INT64_MASK 0x7fFFffFFffFFffFFull
// Macro to build a Posit at compile time
// Note: uses gcc/clang macro extension
// --------------------------------------
// MAKE_POSIT(x, NB, ES)
// x = positive double to be converted into a posit
// NB = number of bits: 8, 16, 32 or 64
// ES = exponent size
//
// * double must be formatted as a biased exponent IEEE 754 binary64 number
// * x must be within range of the posit type
// * 64 bit posits may have missing digits since double has less digits around 1.0
// ---------------------------------------
#define MAKE_POSIT(x, NB, ES) ({ union {double d; uint64_t bits;} f = {x};\
int exp2 = (f.bits >> 52) - 1023;\
int ulen = 1 + ((exp2 >= 0 ? exp2 : -exp2 - 1) >> ES);\
int end1 = NB - 1 - ulen;\
int end2 = NB - ES - 2 - ulen;\
uint64_t e = exp2 & (INT64_MASK >> (63 - ES));\
uint64_t regime = (exp2 >= 0 ? (INT##NB##_MASK >> end1) << end1 : 1ull << (end1 - 1));\
uint64_t fpart = (f.bits << 12);\
uint64_t round2even = (end2 > 1) && (fpart << (end2 - 1)) != (1ull << 62);\
fpart += (round2even << (63 - end2));\
regime | (end2 < 0 ? e >> -end2 : e << end2) | (fpart >> (64 - end2)); })
#define MAKE_POSIT8(x) MAKE_POSIT(x, 8, 0)
#define MAKE_POSIT16(x) MAKE_POSIT(x, 16, 1)
#define MAKE_POSIT32(x) MAKE_POSIT(x, 32, 2)
#define MAKE_POSIT64(x) MAKE_POSIT(x, 64, 3)
#ifdef __cplusplus
}
#endif
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment