#pragma once
#include "include/core/SkMath.h"
#if defined(_MSC_VER)
#include <stdlib.h>
#endif
#if defined(PK_BUILD_FOR_WIN)
#include <intrin.h>
#endif
namespace pk {
constexpr int SkCLZ_portable(uint32_t x) {
int n = 32;
uint32_t y = x >> 16; if (y != 0) {n -= 16; x = y;}
y = x >> 8; if (y != 0) {n -= 8; x = y;}
y = x >> 4; if (y != 0) {n -= 4; x = y;}
y = x >> 2; if (y != 0) {n -= 2; x = y;}
y = x >> 1; if (y != 0) {return n - 2;}
return n - x;
}
static_assert(32 == SkCLZ_portable(0), "");
static_assert(31 == SkCLZ_portable(1), "");
static_assert( 1 == SkCLZ_portable(1 << 30), "");
static_assert( 1 == SkCLZ_portable((1 << 30) | (1 << 24) | 1), "");
static_assert( 0 == SkCLZ_portable(~0U), "");
#if defined(PK_BUILD_FOR_WIN)
static inline int SkCLZ(uint32_t mask) {
if (mask) {
unsigned long index = 0;
_BitScanReverse(&index, mask);
#pragma warning(suppress : 6102)
return index ^ 0x1F;
} else {
return 32;
}
}
#elif defined(PK_CPU_ARM32) || defined(__GNUC__) || defined(__clang__)
static inline int SkCLZ(uint32_t mask) {
return mask ? __builtin_clz(mask) : 32;
}
#else
static inline int SkCLZ(uint32_t mask) {
return SkCLZ_portable(mask);
}
#endif
constexpr int SkCTZ_portable(uint32_t x) {
return 32 - SkCLZ_portable(~x & (x - 1));
}
static_assert(32 == SkCTZ_portable(0), "");
static_assert( 0 == SkCTZ_portable(1), "");
static_assert(30 == SkCTZ_portable(1 << 30), "");
static_assert( 2 == SkCTZ_portable((1 << 30) | (1 << 24) | (1 << 2)), "");
static_assert( 0 == SkCTZ_portable(~0U), "");
#if defined(PK_BUILD_FOR_WIN)
static inline int SkCTZ(uint32_t mask) {
if (mask) {
unsigned long index = 0;
_BitScanForward(&index, mask);
#pragma warning(suppress : 6102)
return index;
} else {
return 32;
}
}
#elif defined(PK_CPU_ARM32) || defined(__GNUC__) || defined(__clang__)
static inline int SkCTZ(uint32_t mask) {
return mask ? __builtin_ctz(mask) : 32;
}
#else
static inline int SkCTZ(uint32_t mask) {
return SkCTZ_portable(mask);
}
#endif
static inline int SkNextLog2(uint32_t value) {
return 32 - SkCLZ(value - 1);
}
template <typename T> static inline bool SkFitsInFixed(T x) {
return SkTAbs(x) <= 32767.0f;
}
}