From a3c69113f461fa28344283092e1dbfa65334c3fa Mon Sep 17 00:00:00 2001 From: Nikolay Puzanov Date: Mon, 27 Jan 2025 22:29:06 +0300 Subject: [PATCH] Add custom div functions --- Makefile | 2 +- idiv.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ idiv.h | 16 +++++++++++ test.c | 2 ++ uprintf.c | 13 ++++++++- 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 idiv.c create mode 100644 idiv.h diff --git a/Makefile b/Makefile index 7fa9752..756a3a1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: test test: test.c uprintf.c uprintf.h - gcc -std=c89 -Os -o test test.c uprintf.c + gcc -std=c89 -Os -DUPRINTF_CUSTOM_DIV_FUNC -o test test.c uprintf.c idiv.c clean: rm -rf test diff --git a/idiv.c b/idiv.c new file mode 100644 index 0000000..7226cc8 --- /dev/null +++ b/idiv.c @@ -0,0 +1,83 @@ +#include +#include "idiv.h" + +#define _IDIV_UU(_INT_WIDTH_) \ + uint ## _INT_WIDTH_ ## _t idiv ## _INT_WIDTH_ ## _uu( \ + uint ## _INT_WIDTH_ ## _t n, \ + uint ## _INT_WIDTH_ ## _t d, \ + uint ## _INT_WIDTH_ ## _t *rp) \ + { \ + uint ## _INT_WIDTH_ ## _t q = 0, r = 0; \ + int i; \ + if (d == 0) { \ + if (rp) *rp = 0; \ + return 0; \ + } \ + for (i = _INT_WIDTH_-1; i >= 0; i --) { \ + r <<= 1; \ + q <<= 1; \ + r |= (n & (1ull << (_INT_WIDTH_-1))) ? 1 : 0; \ + if (r >= d) { \ + r -= d; \ + q |= 1; \ + } \ + n <<= 1; \ + } \ + if (rp) *rp = r; \ + return q; \ + } + + +#define _IDIV_II(_INT_WIDTH_) \ + int ## _INT_WIDTH_ ## _t idiv ## _INT_WIDTH_ ## _ii( \ + int ## _INT_WIDTH_ ## _t n, \ + int ## _INT_WIDTH_ ## _t d, \ + int ## _INT_WIDTH_ ## _t *rp) \ + { \ + uint ## _INT_WIDTH_ ## _t qu = 0, ru = 0, nu, du; \ + int qneg = (n >= 0 && d < 0) | (n < 0 && d >= 0); \ + int rneg = (n < 0); \ + nu = (n < 0) ? -n : n; \ + du = (d < 0) ? -d : d; \ + qu = idiv ## _INT_WIDTH_ ## _uu(nu, du, &ru); \ + if (rp) *rp = rneg ? -ru : ru; \ + return qneg ? -qu : qu; \ + } + +#define _IDIV_UI(_INT_WIDTH_) \ + int ## _INT_WIDTH_ ## _t idiv ## _INT_WIDTH_ ## _ui( \ + uint ## _INT_WIDTH_ ## _t n, \ + int ## _INT_WIDTH_ ## _t d, \ + uint ## _INT_WIDTH_ ## _t *rp) \ + { \ + uint ## _INT_WIDTH_ ## _t qu = 0, ru = 0, du; \ + int qneg = (d < 0); \ + du = (d < 0) ? -d : d; \ + qu = idiv ## _INT_WIDTH_ ## _uu(n, du, &ru); \ + if (rp) *rp = ru; \ + return qneg ? -qu : qu; \ + } + +#define _IDIV_IU(_INT_WIDTH_) \ + int ## _INT_WIDTH_ ## _t idiv ## _INT_WIDTH_ ## _iu( \ + int ## _INT_WIDTH_ ## _t n, \ + uint ## _INT_WIDTH_ ## _t d, \ + int ## _INT_WIDTH_ ## _t *rp) \ + { \ + uint ## _INT_WIDTH_ ## _t qu = 0, ru = 0, nu; \ + int neg = (n < 0); \ + nu = (n < 0) ? -n : n; \ + qu = idiv ## _INT_WIDTH_ ## _uu(nu, d, &ru); \ + if (rp) *rp = neg ? -ru : ru; \ + return neg ? -qu : qu; \ + } + +_IDIV_UU(32) +_IDIV_II(32) +_IDIV_UI(32) +_IDIV_IU(32) + +_IDIV_UU(64) +_IDIV_II(64) +_IDIV_UI(64) +_IDIV_IU(64) diff --git a/idiv.h b/idiv.h new file mode 100644 index 0000000..e2476b9 --- /dev/null +++ b/idiv.h @@ -0,0 +1,16 @@ +#ifndef _IDIV_H_ +#define _IDIV_H_ + +#include + +uint32_t idiv32_uu(uint32_t n, uint32_t d, uint32_t *rp); +int32_t idiv32_ii(int32_t n, int32_t d, int32_t *rp); +int32_t idiv32_ui(uint32_t n, int32_t d, uint32_t *rp); +int32_t idiv32_iu(int32_t n, uint32_t d, int32_t *rp); + +uint64_t idiv64_uu(uint64_t n, uint64_t d, uint64_t *rp); +int64_t idiv64_ii(int64_t n, int64_t d, int64_t *rp); +int64_t idiv64_ui(uint64_t n, int64_t d, uint64_t *rp); +int64_t idiv64_iu(int64_t n, uint64_t d, int64_t *rp); + +#endif diff --git a/test.c b/test.c index 850dcc4..60edf8f 100644 --- a/test.c +++ b/test.c @@ -20,6 +20,8 @@ int main(void) p("7: |%*s|\n", 5, "s"); p("8: |%'-*s|\n", -5, "s"); + p("9: |%016ulx|\n", 0x55555555AAAAAAAAll); + /* TODO more tests */ return 0; diff --git a/uprintf.c b/uprintf.c index 82da79a..1f54ed1 100644 --- a/uprintf.c +++ b/uprintf.c @@ -2,6 +2,10 @@ #include #include "uprintf.h" +#ifdef UPRINTF_CUSTOM_DIV_FUNC +#include "idiv.h" +#endif + /* * ------------------- Простая замена printf ------------------------ * @@ -97,8 +101,15 @@ static void print_decimal(put_char_func pc, uint64_t u, int negative, unsigned i s[si--] = 0; do { - int l = (int)(u % base); + uint64_t l; + +#ifdef UPRINTF_CUSTOM_DIV_FUNC + u = idiv64_uu(u, (uint64_t)base, &l); +#else + l = u % base; u = u / base; +#endif + s[si--] = abet[lcase][l]; } while (u > 0);