diff --git a/src/base_core.h b/src/base_core.h index d1542d9..8a5f7b7 100644 --- a/src/base_core.h +++ b/src/base_core.h @@ -104,12 +104,43 @@ typedef unsigned __int128 U128; (const type *)((const void *)(const unsigned char *)__mptr - offsetof(const type, member)); \ }) -// align needs to be pow2 -#define AlignUp(val, align) (((val) + (align) - 1UL) & ~((align) - 1UL)) -#define AlignDown(val, align) ((val) & ~((align) - 1UL)) -#define IsPow2(x) ((x) && !((x) & ((x) - 1UL))) -#define IsPow2OrZero(x) (!((x) & ((x) - 1UL))) -#define IsAlignedTo(x, align) (IsPow2(align) && !((x) & ((align) - 1UL))) +// `align` must be a power of two. +// +// These keep the result in the *same integer type as the first argument* +#define AlignUp(val, align) \ + ({ \ + __typeof__(val) AlignUp_v_ = (val); \ + __typeof__(val) AlignUp_a_ = (__typeof__(val))(align); \ + (__typeof__(val))((AlignUp_v_ + (AlignUp_a_ - 1)) & \ + ~(__typeof__(val))(AlignUp_a_ - 1)); \ + }) + +#define AlignDown(val, align) \ + ({ \ + __typeof__(val) AlignDown_v_ = (val); \ + __typeof__(val) AlignDown_a_ = (__typeof__(val))(align); \ + (__typeof__(val))(AlignDown_v_ & ~(__typeof__(val))(AlignDown_a_ - 1));\ + }) + +#define IsPow2(x) \ + ({ \ + __typeof__(x) IsPow2_x_ = (x); \ + IsPow2_x_ && !(IsPow2_x_ & (__typeof__(x))(IsPow2_x_ - 1)); \ + }) + +#define IsPow2OrZero(x) \ + ({ \ + __typeof__(x) IsPow2OrZero_x_ = (x); \ + !(IsPow2OrZero_x_ & (__typeof__(x))(IsPow2OrZero_x_ - 1)); \ + }) + +#define IsAlignedTo(x, align) \ + ({ \ + __typeof__(x) IsAlignedTo_x_ = (x); \ + __typeof__(x) IsAlignedTo_a_ = (__typeof__(x))(align); \ + IsPow2(IsAlignedTo_a_) && \ + !(IsAlignedTo_x_ & (__typeof__(x))(IsAlignedTo_a_ - 1)); \ + }) #define GetBit(val, idx) (((val) >> (idx)) & 1) // Get n_bits starting at idx going left