2024-02-24 22:35:25 +05:30
|
|
|
/*
|
|
|
|
* opt_int_div.h
|
|
|
|
*
|
2024-03-24 18:32:31 +05:30
|
|
|
* "Optimized integer division": A header-only library
|
2024-02-25 03:39:36 +05:30
|
|
|
*
|
2024-04-22 02:38:49 +05:30
|
|
|
* NOTE: This code will work only on a computer that uses bits.
|
|
|
|
*
|
2024-02-24 22:35:25 +05:30
|
|
|
* Author: Intel A80486DX2-66
|
2024-04-26 01:46:39 +05:30
|
|
|
* License: Unlicense
|
2024-02-24 22:35:25 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
// helper functions
|
2024-04-22 02:51:44 +05:30
|
|
|
#define INT_BIN_DIV(a, b) ((a) >> (uintmax_t) log2l((b))) /* NOTE: log2l may
|
|
|
|
slow things down */
|
2024-03-09 20:18:05 +05:30
|
|
|
#define INT_DIV_NEG_RESULT_SIGN(a, b) \
|
|
|
|
/* the sign is negative only if one of the numbers is negative */ \
|
2024-03-24 15:55:43 +05:30
|
|
|
(((a) < 0) != ((b) < 0)) /* 1 if sign is negative else 0 */
|
2024-02-24 22:35:25 +05:30
|
|
|
#define INT_ABS(x) ((x) < 0 ? -(x) : (x))
|
2024-03-09 21:59:11 +05:30
|
|
|
#define OPT_INT_DIV_TEST(b) \
|
|
|
|
/* check if b is a power of 2 */ \
|
|
|
|
/* */ \
|
2024-04-22 02:52:49 +05:30
|
|
|
/* condition: ( X & (X - 1) ) == 0 */ \
|
2024-04-22 02:51:44 +05:30
|
|
|
((b) & ((b) - 1)) == 0
|
2024-02-24 22:35:25 +05:30
|
|
|
|
|
|
|
// the main macro
|
|
|
|
#define OPT_INT_DIV(a, b) \
|
|
|
|
( /* beginning */ \
|
2024-04-22 02:52:49 +05:30
|
|
|
/* check for equality of abs(a) and abs(b) */ \
|
2024-02-24 22:35:25 +05:30
|
|
|
INT_ABS((a)) == INT_ABS((b)) ? \
|
2024-03-09 20:18:05 +05:30
|
|
|
/* the result is +/-1 */ \
|
2024-02-24 22:35:25 +05:30
|
|
|
(INT_DIV_NEG_RESULT_SIGN(a, b) ? -1 : 1) : ( \
|
|
|
|
\
|
2024-03-09 20:21:22 +05:30
|
|
|
/* check if abs(a) < abs(b) */ \
|
|
|
|
INT_ABS((a)) < INT_ABS((b)) ? \
|
2024-04-22 02:52:49 +05:30
|
|
|
/* if abs(a) < abs(b), then the result is less than 1 (i.e., 0) */\
|
2024-03-09 20:21:22 +05:30
|
|
|
0 : ( \
|
|
|
|
\
|
2024-03-09 21:59:11 +05:30
|
|
|
OPT_INT_DIV_TEST((b)) ? \
|
|
|
|
(INT_DIV_NEG_RESULT_SIGN(a, b) ? \
|
2024-03-09 20:25:41 +05:30
|
|
|
-INT_BIN_DIV(INT_ABS((a)), INT_ABS((b))) \
|
2024-02-24 22:35:25 +05:30
|
|
|
: \
|
2024-03-09 20:25:41 +05:30
|
|
|
INT_BIN_DIV(INT_ABS((a)), INT_ABS((b)))) \
|
2024-02-24 22:35:25 +05:30
|
|
|
: \
|
2024-03-09 20:21:22 +05:30
|
|
|
((a) / (b)) )) \
|
2024-02-24 22:35:25 +05:30
|
|
|
) /* end */
|