all repos — mgba @ 000b49e45b30ec9c856b7b2e8cf8baee21daa56d

mGBA Game Boy Advance Emulator

include/mgba-util/math.h (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#ifndef UTIL_MATH_H
  7#define UTIL_MATH_H
  8
  9#include <mgba-util/common.h>
 10
 11CXX_GUARD_START
 12
 13static inline uint32_t popcount32(unsigned bits) {
 14	bits = bits - ((bits >> 1) & 0x55555555);
 15	bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
 16	return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
 17}
 18
 19static inline unsigned clz32(uint32_t bits) {
 20#if defined(__GNUC__) || __clang__
 21	if (!bits) {
 22		return 32;
 23	}
 24	return __builtin_clz(bits);
 25#else
 26	static const int table[256] = {
 27		8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
 28		3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 29		2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 30		2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 31		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 32		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 33		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 34		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 35		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 36		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 37		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 38		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 39		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 40		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 41		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 42		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 43	};
 44
 45	if (bits & 0xFF000000) {
 46		return table[bits >> 24];
 47	} else if (bits & 0x00FF0000) {
 48		return table[bits >> 16] + 8;
 49	} else if (bits & 0x0000FF00) {
 50		return table[bits >> 8] + 16;
 51	}
 52	return table[bits] + 24;
 53#endif
 54}
 55
 56static inline unsigned clz64(uint64_t bits) {
 57#if defined(__GNUC__) || __clang__
 58	if (!bits) {
 59		return 64;
 60	}
 61	return __builtin_clzll(bits);
 62#else
 63	static const int table[256] = {
 64		8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
 65		3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 66		2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 67		2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 68		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 69		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 70		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 71		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 72		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 73		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 74		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 75		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 76		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 77		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 78		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 79		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 80	};
 81
 82	if (bits & 0xFF00000000000000) {
 83		return table[bits >> 56];
 84	} else if (bits & 0x00FF000000000000) {
 85		return table[bits >> 48] + 8;
 86	} else if (bits & 0x0000FF0000000000) {
 87		return table[bits >> 40] + 16;
 88	} else if (bits & 0x000000FF00000000) {
 89		return table[bits >> 32] + 24;
 90	} else if (bits & 0x00000000FF000000) {
 91		return table[bits >> 24] + 32;
 92	} else if (bits & 0x0000000000FF0000) {
 93		return table[bits >> 16] + 40;
 94	} else if (bits & 0x000000000000FF00) {
 95		return table[bits >> 8] + 48;
 96	}
 97	return table[bits] + 56;
 98#endif
 99}
100
101static inline uint32_t toPow2(uint32_t bits) {
102	if (!bits) {
103		return 0;
104	}
105	unsigned lz = clz32(bits - 1);
106	return 1 << (32 - lz);
107}
108
109static inline int reduceFraction(int* num, int* den) {
110	int n = *num;
111	int d = *den;
112	while (d != 0) {
113		int temp = n % d;
114		n = d;
115		d = temp;
116	}
117	*num /= n;
118	*den /= n;
119	return n;
120}
121
122CXX_GUARD_END
123
124#endif