2024-02-24 22:35:25 +05:30
|
|
|
/*
|
|
|
|
* opt_int_div.h
|
|
|
|
*
|
2024-02-25 03:39:36 +05:30
|
|
|
* "Optimized integer division"
|
|
|
|
*
|
2024-02-24 22:35:25 +05:30
|
|
|
* Author: Intel A80486DX2-66
|
|
|
|
* License: Creative Commons Zero 1.0 Universal
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
// parameters
|
|
|
|
#define OPT_INT_DIV_TEST_PRECISION 8
|
|
|
|
|
|
|
|
// constants
|
|
|
|
#define OPT_INT_DIV_ROUNDING \
|
2024-03-09 19:20:35 +05:30
|
|
|
/* formula: 10^OPT_INT_DIV_TEST_PRECISION */ \
|
2024-03-09 19:19:33 +05:30
|
|
|
powl(10.l, (long double) OPT_INT_DIV_TEST_PRECISION)
|
2024-02-24 22:35:25 +05:30
|
|
|
|
|
|
|
// helper functions
|
|
|
|
#define INT_BIN_DIV(a, b) ((a) >> (uintmax_t) log2l((b)))
|
|
|
|
#define INT_DIV_NEG_RESULT_SIGN(a, b) (((a) < 0) ^ ((b) < 0))
|
|
|
|
#define INT_ABS(x) ((x) < 0 ? -(x) : (x))
|
|
|
|
|
|
|
|
// the main macro
|
|
|
|
#define OPT_INT_DIV(a, b) \
|
|
|
|
( /* beginning */ \
|
|
|
|
/* check for equality of a and b */ \
|
|
|
|
INT_ABS((a)) == INT_ABS((b)) ? \
|
|
|
|
/* if only one of the numbers is negative, the result is -1, */ \
|
|
|
|
/* otherwise it is 1. */ \
|
|
|
|
(INT_DIV_NEG_RESULT_SIGN(a, b) ? -1 : 1) : ( \
|
|
|
|
\
|
|
|
|
/* check if b is a power of 2 */ \
|
|
|
|
/* */ \
|
|
|
|
/* formula: round(log_2(b) % 1, OPT_INT_DIV_TEST_PRECISION digits */ \
|
|
|
|
/* after point) == 0 */ \
|
2024-02-25 03:37:22 +05:30
|
|
|
(roundl(fmodl(log2l((b)), 1.l) * OPT_INT_DIV_ROUNDING) == 0.l) ? ( \
|
2024-02-24 22:35:25 +05:30
|
|
|
/* if only one of the numbers is negative, the result is */ \
|
|
|
|
/* negative */ \
|
|
|
|
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 */
|