#pragma once #include #include template constexpr inline T is_aligned(T value) { return (value % alignment == 0); } static_assert(is_aligned<512>(1024u)); static_assert(!is_aligned<32>(235u)); static_assert(is_aligned<4096>(40960u)); template constexpr inline T align_down(T value) { return value - value % alignment; } static_assert(align_down<512>(598ul) == 512ul); static_assert(align_down<64>(194ul) == 192ul); static_assert(align_down<32>(64ul) == 64ul); template constexpr inline T align_up(T value) { if (is_aligned(value)) return value; return align_down(value) + alignment; } static_assert(align_up<512>(598ul) == 1024ul); static_assert(align_up<64>(194ul) == 256ul); static_assert(align_up<32>(64ul) == 64ul); // Offset a pointer by exactly bytes, no matter the type. Useful to avoid the quirks that come from C pointer // arithmetic. template constexpr inline T* offset_ptr(T* ptr, Offset offset) { return (T*)((u8*)ptr + offset); }