#pragma once #include #include // // sign_extend // static inline int32_t sign_extend(uint32_t x, uint32_t b) { const uint32_t m = 1UL << (b - 1); x = x & ((1UL << b) - 1); const int32_t r = (x ^ m) - m; return r; } static inline int64_t sign_extend64(uint64_t x) { return (int64_t)x; } static inline int32_t sign_extend32(uint32_t x) { return (int32_t)x; } static inline int32_t sign_extend16(uint32_t x) { return sign_extend(x, 16); } static inline int32_t sign_extend12(uint32_t x) { return sign_extend(x, 12); } static inline int32_t sign_extend8(uint32_t x) { return sign_extend(x, 8); } // // zero_extend // static inline uint32_t zero_extend(uint32_t x, uint32_t b) { x = x & ((1ULL << b) - 1); return x; } static inline uint32_t zero_extend32(uint32_t x) { return (uint32_t)x; } static inline uint32_t zero_extend16(uint32_t x) { return zero_extend(x, 16); } static inline uint32_t zero_extend8(uint32_t x) { return zero_extend(x, 8); } static inline uint32_t zero_extend4(uint32_t x) { return zero_extend(x, 4); } static inline uint32_t zero_extend1(uint32_t x) { return zero_extend(x, 1); } // // signed_saturate // static inline uint64_t signed_saturate(uint64_t x, uint32_t b) { const int64_t upper = (1LL << (b - 1)) - 1; const int64_t lower = -(1LL << (b - 1)); static_assert(-(1LL << (48 - 1)) < 0); if (x > upper) return upper; else if (x < lower) return lower; else return x; } static inline uint64_t signed_saturate48(uint64_t x) { return signed_saturate(x, 48); } static inline uint32_t signed_saturate32(uint32_t x) { return signed_saturate(x, 32); } // // "convenience" functions // static inline uint32_t _register(uint32_t x) { return zero_extend(x, 32); } static inline uint32_t bit(uint32_t x) { return zero_extend(x, 1); } // // "operations" // static inline int32_t unary_int(int64_t x) { return x != 0; } static inline int64_t bit_extract(int64_t n, int64_t b, int64_t m) { return (n >> b) & ((1 << m) - 1); }