From bc443e31c36be747155298eb6229d3e91b77dd7f Mon Sep 17 00:00:00 2001 From: bumbread Date: Fri, 5 Aug 2022 20:00:58 +1100 Subject: [PATCH] separate out conv stuff --- src/ciabatta.c | 10 +- src/{ => conv}/decfloat/decfloat.c | 0 src/{ => conv}/decfloat/decfloat_table.h | 0 src/conv/digits.c | 32 +++++ src/conv/float.c | 130 +++++++++++++++++ src/conv/{conversion.c => int.c} | 173 +---------------------- src/conv/strpfx.c | 10 ++ src/util.c | 5 +- 8 files changed, 183 insertions(+), 177 deletions(-) rename src/{ => conv}/decfloat/decfloat.c (100%) rename src/{ => conv}/decfloat/decfloat_table.h (100%) create mode 100644 src/conv/digits.c create mode 100644 src/conv/float.c rename src/conv/{conversion.c => int.c} (52%) create mode 100644 src/conv/strpfx.c diff --git a/src/ciabatta.c b/src/ciabatta.c index d2eaccf..bc9834d 100644 --- a/src/ciabatta.c +++ b/src/ciabatta.c @@ -37,10 +37,9 @@ #include "intrin.h" -#include "util.c" - // Dependencies -#include "decfloat/decfloat.c" +#include "util.c" +#include "conv/decfloat/decfloat.c" // Platform-independent stuff #include "fmt/gen_fmt.c" @@ -49,7 +48,10 @@ #include "math/gen_math.c" #include "math/ieee754.c" #include "math/round.c" -#include "conv/conversion.c" +#include "conv/digits.c" +#include "conv/strpfx.c" +#include "conv/int.c" +#include "conv/float.c" #include "stdlib/algorithm.c" #include "stdlib/multibyte.c" #include "stdlib/random.c" diff --git a/src/decfloat/decfloat.c b/src/conv/decfloat/decfloat.c similarity index 100% rename from src/decfloat/decfloat.c rename to src/conv/decfloat/decfloat.c diff --git a/src/decfloat/decfloat_table.h b/src/conv/decfloat/decfloat_table.h similarity index 100% rename from src/decfloat/decfloat_table.h rename to src/conv/decfloat/decfloat_table.h diff --git a/src/conv/digits.c b/src/conv/digits.c new file mode 100644 index 0000000..dc4a8aa --- /dev/null +++ b/src/conv/digits.c @@ -0,0 +1,32 @@ + +static inline bool isbase(int c, int base) { + int val = 0; + if(isdigit(c)) { + val = c-'0'; + } + else if(islower(c)) { + val = c-'a'+10; + } + else if(isupper(c)) { + val = c-'A'+10; + } + else { + return false; + } + return val < base; +} + +static inline intl todigit(int c) { + int val = 0; + if(isdigit(c)) { + val = c-'0'; + } + else if(islower(c)) { + val = c-'a'+10; + } + else if(isupper(c)) { + val = c-'A'+10; + } + return val; +} + diff --git a/src/conv/float.c b/src/conv/float.c new file mode 100644 index 0000000..f0e1b7b --- /dev/null +++ b/src/conv/float.c @@ -0,0 +1,130 @@ + + +static f64 strtod_generic(const char *restrict nptr, char **restrict endptr) { + const char *restrict str = nptr; + bool conv_performed = false; + f64 value = 0.0; + f64 coef = 1.0; + // Skip space on the beginning + while(isspace(*str)) { + ++str; + } + // Check for inf and nan + if(strpfx_i(str, "INF")) { + str += sizeof "INF"-1; + value = HUGE_VAL; + conv_performed = true; + goto finish; + } + if(strpfx_i(str, "INFINITY")) { + str += sizeof "INFINITY"-1; + value = HUGE_VAL; + conv_performed = true; + goto finish; + } + if(strpfx_i(str, "NAN")) { + str += sizeof "NAN"-1; + value = NAN; + conv_performed = true; + if(*str == '(') { + while(*str != ')') { + ++str; + } + ++str; + } + goto finish; + } + // Parse C float + if(*str == '+') { + ++str; + } + else if(*str == '-') { + coef = -1.; + ++str; + } + int base = 10; + if(strpfx_i(str, "0X")) { + str += sizeof "0X"-1; + base = 16; + } + // Parse the whole part + while(isbase(*str, base)) { + long digit = todigit(*str); + value = 10.0*value + (f64)digit; + ++str; + } + if(*str != '.') { + value = 0.0; + goto finish; + } + ++str; + // Parse the fractional part + long exp = 1; + while(isbase(*str, base)) { + long digit = todigit(*str); + f64 fract = (f64)digit; + long cexp = exp; + while(cexp-- != 0) { + fract /= (f64)base; + } + value += fract; + ++exp; + ++str; + } + // Parse the exponent + if((base == 10 && strpfx_i(str, "E")) + || (base == 16 && strpfx_i(str, "P"))) + { + ++str; + long exp = 0; + long exp_coef = 1; + if(*str == '+') { + ++str; + } + else if(*str == '-') { + exp_coef = -1; + ++str; + } + while(isdigit(*str)) { + exp = 10*exp + (long)(*str-'0'); + ++str; + } + if(exp_coef == 1) { + while(exp--!=0) value = value * base; + } + else if(exp_coef == -1) { + while(exp--!=0) value = value / base; + } + } + if(!isfinite(value)) { + errno = ERANGE; + value = coef*HUGE_VAL; + } + conv_performed = true; + finish: + if(endptr != NULL) { + if(conv_performed) { + *endptr = (char *)str; + } + else { + *endptr = (char *)nptr; + } + } + return coef*value; +} + +f64 strtod(const char *restrict nptr, char **restrict endptr) { + return strtod_generic(nptr, endptr); +} + +f32 strtof(const char *restrict nptr, char **restrict endptr) { + return (f32)strtod_generic(nptr, endptr); +} + +fl64 strtold(const char *restrict nptr, char **restrict endptr) { + return (fl64)strtod_generic(nptr, endptr); +} + +f64 atof(const char *nptr) { + return strtod(nptr, (char **)NULL); +} diff --git a/src/conv/conversion.c b/src/conv/int.c similarity index 52% rename from src/conv/conversion.c rename to src/conv/int.c index 6761773..05afcc8 100644 --- a/src/conv/conversion.c +++ b/src/conv/int.c @@ -1,46 +1,4 @@ -static bool isbase(int c, int base) { - int val = 0; - if(isdigit(c)) { - val = c-'0'; - } - else if(islower(c)) { - val = c-'a'+10; - } - else if(isupper(c)) { - val = c-'A'+10; - } - else { - return false; - } - return val < base; -} - -static bool strprefix_i(char const *restrict str, char const *restrict prefix) { - while(*prefix != 0) { - if(*str == 0) break; - if(toupper(*str) != toupper(*prefix)) return false; - ++prefix; - ++str; - } - return true; -} - -// Called only when isbase(c, base) for some base in range -static long todigit(int c) { - int val = 0; - if(isdigit(c)) { - val = c-'0'; - } - else if(islower(c)) { - val = c-'a'+10; - } - else if(isupper(c)) { - val = c-'A'+10; - } - return val; -} - static intull strtoi_generic(const char *restrict nptr, char **restrict endptr, int inbase, @@ -77,7 +35,7 @@ static intull strtoi_generic(const char *restrict nptr, } // See if we need to parse base in C-like format // then set the base accordingly - if(strprefix_i(str, "0X")) { + if(strpfx_i(str, "0X")) { ++str; if(base == 16 || base == 0) { ++str; @@ -140,119 +98,6 @@ static intull strtoi_generic(const char *restrict nptr, return value; } -static double strtod_generic(const char *restrict nptr, char **restrict endptr) { - const char *restrict str = nptr; - bool conv_performed = false; - double value = 0.0; - double coef = 1.0; - // Skip space on the beginning - while(isspace(*str)) { - ++str; - } - // Check for inf and nan - if(strprefix_i(str, "INF")) { - str += sizeof "INF"-1; - value = HUGE_VAL; - conv_performed = true; - goto finish; - } - if(strprefix_i(str, "INFINITY")) { - str += sizeof "INFINITY"-1; - value = HUGE_VAL; - conv_performed = true; - goto finish; - } - if(strprefix_i(str, "NAN")) { - str += sizeof "NAN"-1; - value = NAN; - conv_performed = true; - if(*str == '(') { - while(*str != ')') { - ++str; - } - ++str; - } - goto finish; - } - // Parse C float - if(*str == '+') { - ++str; - } - else if(*str == '-') { - coef = -1.; - ++str; - } - int base = 10; - if(strprefix_i(str, "0X")) { - str += sizeof "0X"-1; - base = 16; - } - // Parse the whole part - while(isbase(*str, base)) { - long digit = todigit(*str); - value = 10.0*value + (double)digit; - ++str; - } - if(*str != '.') { - value = 0.0; - goto finish; - } - ++str; - // Parse the fractional part - long exp = 1; - while(isbase(*str, base)) { - long digit = todigit(*str); - double fract = (double)digit; - long cexp = exp; - while(cexp-- != 0) { - fract /= (double)base; - } - value += fract; - ++exp; - ++str; - } - // Parse the exponent - if((base == 10 && strprefix_i(str, "E")) - || (base == 16 && strprefix_i(str, "P"))) - { - ++str; - long exp = 0; - long exp_coef = 1; - if(*str == '+') { - ++str; - } - else if(*str == '-') { - exp_coef = -1; - ++str; - } - while(isdigit(*str)) { - exp = 10*exp + (long)(*str-'0'); - ++str; - } - if(exp_coef == 1) { - while(exp--!=0) value = value * base; - } - else if(exp_coef == -1) { - while(exp--!=0) value = value / base; - } - } - if(!isfinite(value)) { - errno = ERANGE; - value = coef*HUGE_VAL; - } - conv_performed = true; - finish: - if(endptr != NULL) { - if(conv_performed) { - *endptr = (char *)str; - } - else { - *endptr = (char *)nptr; - } - } - return coef*value; -} - intl strtol(const char *restrict nptr, char **restrict endptr, int base) { intull int_max = (intull)LONG_MAX; intl coef; @@ -292,10 +137,6 @@ intull strtoull(const char *restrict nptr, char **restrict endptr, int base) { return strtoi_generic(nptr, endptr, base, NULL, int_max); } -double atof(const char *nptr) { - return strtod(nptr, (char **)NULL); -} - int atoi(const char *nptr) { return (int)strtol(nptr, (char **)NULL, 10); } @@ -308,18 +149,6 @@ long long int atoll(const char *nptr) { return strtoll(nptr, (char **)NULL, 10); } -double strtod(const char *restrict nptr, char **restrict endptr) { - return strtod_generic(nptr, endptr); -} - -float strtof(const char *restrict nptr, char **restrict endptr) { - return (float)strtod_generic(nptr, endptr); -} - -long double strtold(const char *restrict nptr, char **restrict endptr) { - return (long double)strtod_generic(nptr, endptr); -} - char *itoa(int value, char *str, int base) { int sign = 0; if(value < 0) { diff --git a/src/conv/strpfx.c b/src/conv/strpfx.c new file mode 100644 index 0000000..b15a454 --- /dev/null +++ b/src/conv/strpfx.c @@ -0,0 +1,10 @@ + +static bool strpfx_i(char const *restrict str, char const *restrict prefix) { + while(*prefix != 0) { + if(*str == 0) break; + if(toupper(*str) != toupper(*prefix)) return false; + ++prefix; + ++str; + } + return true; +} diff --git a/src/util.c b/src/util.c index 4ed8555..abcb215 100644 --- a/src/util.c +++ b/src/util.c @@ -32,9 +32,12 @@ typedef unsigned int intu; typedef unsigned long int intul; typedef unsigned long long int intull; +typedef float f32; +typedef double f64; +typedef long double fl64; + typedef wchar_t wchar; -#define COUNTOF(arr) (sizeof (arr) / sizeof ((arr)[0])) #define IN_RANGE(start, v, end) ((start) <= (v) && (v) <= (end)) #define CONCAT(a,b) a ## b