1
0
mirror of https://gitlab.com/80486DX2-66/gists synced 2024-12-28 00:00:18 +05:30
gists/c-programming/math/opt_int_div.h

59 lines
3.1 KiB
C

/*
* opt_int_div.h
*
* "Optimized integer division": A header-only library
*
* Author: Intel A80486DX2-66
* License: Creative Commons Zero 1.0 Universal
*/
#include <math.h>
#include <stdint.h>
// parameters
#define OPT_INT_DIV_IS_TEST_PRECISION_LIMITED 0 /* true (1) or false (0) */
#define OPT_INT_DIV_TEST_PRECISION 8 /* only if the above parameter is 1 */
// constants
#define OPT_INT_DIV_ROUNDING \
/* formula: 10^OPT_INT_DIV_TEST_PRECISION */ \
powl(10.l, (long double) OPT_INT_DIV_TEST_PRECISION)
// helper functions
#define INT_BIN_DIV(a, b) ((a) >> (uintmax_t) log2l((b)))
#define INT_DIV_NEG_RESULT_SIGN(a, b) \
/* the sign is negative only if one of the numbers is negative */ \
(((a) < 0) != ((b) < 0)) /* 1 if sign is negative else 0 */
#define INT_ABS(x) ((x) < 0 ? -(x) : (x))
#define LOG2_DEC_PORTION(b) fmodl(log2l(INT_ABS((b))), 1.l)
#define OPT_INT_DIV_TEST(b) \
/* check if b is a power of 2 */ \
/* */ \
/* formula: round(log_2(b) % 1, OPT_INT_DIV_TEST_PRECISION digits */ \
/* after point) == 0 */ \
OPT_INT_DIV_IS_TEST_PRECISION_LIMITED ? \
roundl(LOG2_DEC_PORTION((b)) * OPT_INT_DIV_ROUNDING) == 0.l \
: \
LOG2_DEC_PORTION((b)) == 0.l
// the main macro
#define OPT_INT_DIV(a, b) \
( /* beginning */ \
/* check for equality of a and b */ \
INT_ABS((a)) == INT_ABS((b)) ? \
/* the result is +/-1 */ \
(INT_DIV_NEG_RESULT_SIGN(a, b) ? -1 : 1) : ( \
\
/* check if abs(a) < abs(b) */ \
INT_ABS((a)) < INT_ABS((b)) ? \
0 : ( \
\
OPT_INT_DIV_TEST((b)) ? \
(INT_DIV_NEG_RESULT_SIGN(a, b) ? \
-INT_BIN_DIV(INT_ABS((a)), INT_ABS((b))) \
: \
INT_BIN_DIV(INT_ABS((a)), INT_ABS((b)))) \
: \
((a) / (b)) )) \
) /* end */