[ create a new paste ] login | about

Link: http://codepad.org/GcI7hJay    [ raw code | fork ]

C, pasted on Feb 9:
#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);
}


Create a new paste based on this one


Comments: