mirror of
https://gitlab.com/80486DX2-66/gists
synced 2025-01-10 08:27:48 +05:30
C: add opt_int_div.*
This commit is contained in:
parent
a73f75c489
commit
0ef6c03393
44
c-programming/math/opt_int_div.c
Normal file
44
c-programming/math/opt_int_div.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* opt_int_div.c
|
||||
*
|
||||
* Author: Intel A80486DX2-66
|
||||
* License: Creative Commons Zero 1.0 Universal
|
||||
*/
|
||||
|
||||
#include "opt_int_div.h"
|
||||
|
||||
#ifdef TEST
|
||||
# include <inttypes.h>
|
||||
# include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
printf("Loop: a > 0, b > 0\n");
|
||||
for (uint8_t a = 3; a <= 24; a++)
|
||||
for (uint8_t b = 1; b <= 8; b++) {
|
||||
if (b >= a)
|
||||
break;
|
||||
printf("%" PRIu8 " / %" PRIu8 " = %" PRIu8 "\n", a, b,
|
||||
OPT_INT_DIV(a, b));
|
||||
}
|
||||
|
||||
printf("Loop: a < 0, b > 0\n");
|
||||
for (int8_t a = -3; a >= -24; a--)
|
||||
for (int8_t b = 1; b <= 8; b++) {
|
||||
if (b >= abs(a))
|
||||
break;
|
||||
printf("%" PRId8 " / %" PRId8 " = %" PRId8 "\n", a, b,
|
||||
OPT_INT_DIV(a, b));
|
||||
}
|
||||
|
||||
printf("Loop: a < 0, b < 0\n");
|
||||
for (int8_t a = -3; a >= -24; a--)
|
||||
for (int8_t b = -1; b >= -8; b--) {
|
||||
if (b <= a)
|
||||
break;
|
||||
printf("%" PRId8 " / %" PRId8 " = %" PRId8 "\n", a, b,
|
||||
OPT_INT_DIV(a, b));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
47
c-programming/math/opt_int_div.h
Normal file
47
c-programming/math/opt_int_div.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* opt_int_div.h
|
||||
*
|
||||
* 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 \
|
||||
/* 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) (((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 */ \
|
||||
(roundl(fmodl(log2l((b)), 1.l) * OPT_INT_DIV_ROUNDING) / \
|
||||
OPT_INT_DIV_ROUNDING == 0.l) ? ( \
|
||||
/* 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 */
|
Loading…
x
Reference in New Issue
Block a user