#ifndef USE_TABLE
#include <stdlib.h>
#else
#include <string.h>
#endif
#ifndef USE_TABLE
static inline void handle_special_cases(char **s, int x, char c1, char c2,
char c3)
{
if (x == 9) {
*(*s)++ = c1;
*(*s)++ = c3;
} else if (x >= 5) {
*(*s)++ = c2;
for (int i = 5; i < x; ++i)
*(*s)++ = c1;
} else if (x == 4) {
*(*s)++ = c2;
*(*s)++ = c1;
} else {
for (int i = 0; i < x; ++i)
*(*s)++ = c1;
}
}
int to_roman(char * restrict s, int x)
{
char *c = s;
div_t d = div(x, 1000);
for (int i = 0; i < d.quot; ++i)
*c++ = 'M';
handle_special_cases(&c, (d = div(d.rem, 100)).quot, 'C', 'D', 'M');
handle_special_cases(&c, (d = div(d.rem, 10)).quot, 'X', 'L', 'C');
handle_special_cases(&c, d.rem, 'I', 'V', 'X');
*c = '\0';
return (int)(c - s);
}
#else
int to_roman(char * restrict str, int val)
{
#ifndef CACHE_SIZE
static const struct {int val; const char *str;} tbl[] = {
{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"},
{90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {5, "V"}, {4, "IV"},
{1, "I"}
};
#else
static const struct {int val; const char *str; size_t sz;} tbl[] = {
{1000, "M", 1}, {900, "CM", 2}, {500, "D", 1}, {400, "CD", 2},
{100, "C", 1}, {90, "XC", 2}, {50, "L", 1}, {40, "XL", 2},
{10, "X", 1}, {5, "V", 1}, {4, "IV", 2}, {1, "I", 1}
};
#endif
char *wrt = str;
for (int i = 0; i < sizeof(tbl) / sizeof(*tbl); ++i) {
for (; val >= tbl[i].val; val -= tbl[i].val) {
#ifndef CACHE_SIZE
const char *ch = tbl[i].str;
while (*ch)
*wrt++ = *ch++;
#else
__builtin_memcpy(wrt, tbl[i].str, tbl[i].sz);
wrt += tbl[i].sz;
#endif
}
}
*wrt = '\0';
return (int)(wrt - str);
}
#endif
int main()
{
static char str[sizeof("MMMMMMMMMDCCCLXXXVIII")];
for (int i = 0; i < ITERATIONS; ++i)
to_roman(str, 9999);
}