// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once #include "types.h" #include #ifdef _MSC_VER #include #endif namespace Common { template constexpr bool IsAligned(T value, unsigned int alignment) { return (value % static_cast(alignment)) == 0; } template constexpr T AlignUp(T value, unsigned int alignment) { return (value + static_cast(alignment - 1)) / static_cast(alignment) * static_cast(alignment); } template constexpr T AlignDown(T value, unsigned int alignment) { return value / static_cast(alignment) * static_cast(alignment); } template constexpr bool IsAlignedPow2(T value, unsigned int alignment) { return (value & static_cast(alignment - 1)) == 0; } template constexpr T AlignUpPow2(T value, unsigned int alignment) { return (value + static_cast(alignment - 1)) & static_cast(~static_cast(alignment - 1)); } template constexpr T AlignDownPow2(T value, unsigned int alignment) { return value & static_cast(~static_cast(alignment - 1)); } template constexpr bool IsPow2(T value) { return (value & (value - 1)) == 0; } template constexpr T PreviousPow2(T value) { if (value == static_cast(0)) return 0; value |= (value >> 1); value |= (value >> 2); value |= (value >> 4); value |= (value >> 8); value |= (value >> 16); return value - (value >> 1); } ALWAYS_INLINE static void* AlignedMalloc(size_t size, size_t alignment) { #ifdef _MSC_VER return _aligned_malloc(size, alignment); #else // Unaligned sizes are slow on macOS. #ifdef __APPLE__ if (IsPow2(alignment)) size = (size + alignment - 1) & ~(alignment - 1); #endif void* ret = nullptr; posix_memalign(&ret, alignment, size); return ret; #endif } ALWAYS_INLINE static void AlignedFree(void* ptr) { #ifdef _MSC_VER _aligned_free(ptr); #else free(ptr); #endif } } // namespace Common