Add custom div functions

This commit is contained in:
Nikolay Puzanov 2025-01-27 22:29:06 +03:00
parent 60245f9da0
commit a3c69113f4
5 changed files with 114 additions and 2 deletions

View File

@ -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

83
idiv.c Normal file
View File

@ -0,0 +1,83 @@
#include <stdint.h>
#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)

16
idiv.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _IDIV_H_
#define _IDIV_H_
#include <stdint.h>
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

2
test.c
View File

@ -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;

View File

@ -2,6 +2,10 @@
#include <stdarg.h>
#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);