/* * opt_int_div.h * * "Optimized integer division" * * Author: Intel A80486DX2-66 * License: Creative Commons Zero 1.0 Universal */ #include #include // 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 */