Learn-to-Compress / headers / forutil.h
forutil.h
Raw
#ifndef FRAMEOFREFERENCE_INCLUDE_UTIL_H
#define FRAMEOFREFERENCE_INCLUDE_UTIL_H
#include <iso646.h> // mostly for Microsoft 
#ifdef _MSC_VER
/* Microsoft C/C++-compatible compiler */
#include <intrin.h>

#ifndef __clang__ // if one compiles with MSVC *with* clang, then these intrinsics are defined!!!
// sadly there is no way to check whether we are missing these intrinsics specifically.

/* wrappers for Visual Studio built-ins that look like gcc built-ins */
/* result might be undefined when input_num is zero */
static inline int __builtin_ctzll(unsigned long long input_num) {
	unsigned long index;
#ifdef _WIN64 // highly recommended!!!
	_BitScanForward64(&index, input_num);
#else // if we must support 32-bit Windows
	if ((uint32_t)input_num != 0) {
		_BitScanForward(&index, (uint32_t)input_num);
	}
	else {
		_BitScanForward(&index, (uint32_t)(input_num >> 32));
		index += 32;
	}
#endif
	return index;
}

/* result might be undefined when input_num is zero */
static inline int __builtin_clzll(unsigned long long input_num) {
	unsigned long index;
#ifdef _WIN64 // highly recommended!!!
	_BitScanReverse64(&index, input_num);
#else // if we must support 32-bit Windows
	if (input_num > 0xFFFFFFF) {
		_BitScanReverse(&index, (uint32_t)(input_num >> 32));
	}
	else {
		_BitScanReverse(&index, (uint32_t)(input_num));
		index += 32;
	}
#endif
	return 63 - index;
}

/* result might be undefined when input_num is zero */
static inline int __builtin_clz(int input_num) {
	unsigned long index;
	_BitScanReverse(&index, input_num);
	return 31 - index;
}

/* result might be undefined when input_num is zero */
static inline int __builtin_popcountll(unsigned long long input_num) {
#ifdef _WIN64 // highly recommended!!!
	return (int)__popcnt64(input_num);
#else // if we must support 32-bit Windows
	return (int)(__popcnt((uint32_t)input_num) + __popcnt((uint32_t)(input_num >> 32)));
#endif
}

static inline void __builtin_unreachable() {
	__assume(0);
}
#endif
#endif


#include <stdint.h> // part of Visual Studio 2010 and better

// integer logarithm function
static inline uint32_t bits(const uint32_t v) {
    return v == 0 ? 0 : 32 - __builtin_clz(v); // todo: make portable (Visual studio)
}



// integer logarithm function
static inline uint32_t bits64(const uint64_t v) {
    return v == 0 ? 0 : 64 - __builtin_clzll(v); // todo: make portable (Visual studio)
}

#endif // FRAMEOFREFERENCE_INCLUDE_UTIL_H