diff --git a/stix/configure b/stix/configure index 7f84227..121a74b 100755 --- a/stix/configure +++ b/stix/configure @@ -18074,6 +18074,111 @@ esac LIBM=$LIBM +check some compiler builtins +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memset" >&5 +$as_echo_n "checking __builtin_memset... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__builtin_memset ((void*)1, ' ', 10); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE___BUILTIN_MEMSET 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memcpy" >&5 +$as_echo_n "checking __builtin_memcpy... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__builtin_memcpy ((void*)1, (void*)2, 10); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE___BUILTIN_MEMCPY 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memmove" >&5 +$as_echo_n "checking __builtin_memmove... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__builtin_memmove ((void*)1, (void*)2, 10); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE___BUILTIN_MEMMOVE 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __builtin_memcmp" >&5 +$as_echo_n "checking __builtin_memcmp... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int a = __builtin_memcmp ((void*)1, (void*)2, 10); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE___BUILTIN_MEMCMP 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : diff --git a/stix/configure.ac b/stix/configure.ac index 1b593fd..83ad42a 100644 --- a/stix/configure.ac +++ b/stix/configure.ac @@ -118,6 +118,39 @@ dnl check the math library (check if -lm is needed) LT_LIB_M AC_SUBST(LIBM, $LIBM) +check some compiler builtins +AC_MSG_CHECKING([__builtin_memset]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [__builtin_memset ((void*)1, ' ', 10);])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE___BUILTIN_MEMSET], [1], [__builtin_memset])], + [AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING([__builtin_memcpy]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [__builtin_memcpy ((void*)1, (void*)2, 10);])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE___BUILTIN_MEMCPY], [1], [__builtin_memcpy])], + [AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING([__builtin_memmove]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [__builtin_memmove ((void*)1, (void*)2, 10);])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE___BUILTIN_MEMMOVE], [1], [__builtin_memmove])], + [AC_MSG_RESULT(no)] +) + +AC_MSG_CHECKING([__builtin_memcmp]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [int a = __builtin_memcmp ((void*)1, (void*)2, 10);])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE___BUILTIN_MEMCMP], [1], [__builtin_memcmp])], + [AC_MSG_RESULT(no)] +) + dnl check header files. AC_HEADER_STDC AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h]) diff --git a/stix/lib/bigint.c b/stix/lib/bigint.c index 37a01ec..72c5e04 100644 --- a/stix/lib/bigint.c +++ b/stix/lib/bigint.c @@ -87,7 +87,7 @@ static STIX_INLINE int is_integer (stix_t* stix, stix_oop_t oop) c = STIX_CLASSOF(stix,oop); -/* TODO: is it better to introduct a special integer mark into the class itself */ +/* TODO: is it better to introduce a special integer mark into the class itself */ return c == stix->_small_integer || c == stix->_large_positive_integer || c == stix->_large_negative_integer; @@ -615,12 +615,11 @@ stix_oop_t stix_strtoint (stix_t* stix, const stix_ooch_t* str, stix_oow_t len, /* bytes */ outlen = ((stix_oow_t)(end - str) * exp + 7) / 8; /* number of stix_oohw_t */ - outlen = (outlen + STIX_SIZEOF(stix_oohw_t) - 1) / STIX_SIZEOF(stix_oohw_t); -/* TODO: use a precomputed table for outlen instead of calculating here */ + outlen = (outlen + STIX_SIZEOF(hw[0]) - 1) / STIX_SIZEOF(hw[0]); if (outlen > STIX_COUNTOF(hw)) { - hwp = stix_allocmem (stix, outlen * STIX_SIZEOF(stix_oohw_t)); + hwp = stix_allocmem (stix, outlen * STIX_SIZEOF(hw[0])); if (!hwp) return STIX_NULL; } else @@ -655,15 +654,37 @@ stix_oop_t stix_strtoint (stix_t* stix, const stix_ooch_t* str, stix_oow_t len, } else { - stix_oow_t r1, r2; + stix_oow_t r1, r2, ub; stix_oohw_t multiplier; - int dg, i, max_ndigits; + int dg, i, safe_ndigits; w = 0; ptr = start; -max_ndigits = 9; /* GET THIS */ - outlen = (end - str) / max_ndigits + 1; + if (stix->bigint[radix].safe_ndigits > 0) + { + /* if the table entry has been initialized properly, + * take it instead of recalculation. */ + safe_ndigits = stix->bigint[radix].safe_ndigits; + multiplier = stix->bigint[radix].multiplier; + } + else + { + r1 = 0; + ub = STIX_TYPE_MAX(stix_oohw_t) / radix - (radix - 1); + multiplier = 1; + for (safe_ndigits = 0; r1 <= ub; safe_ndigits++) + { + r1 = r1 * radix + (radix - 1); + multiplier *= radix; + } + /* safe_ndigits contains the number of digits that never + * cause overflow when computed normally with a native type. */ + stix->bigint[radix].safe_ndigits = safe_ndigits; + stix->bigint[radix].multiplier = multiplier; + } + + outlen = (end - str) / safe_ndigits + 1; if (outlen > STIX_COUNTOF(hw)) { hwp = stix_allocmem (stix, outlen * STIX_SIZEOF(stix_oohw_t)); @@ -673,13 +694,12 @@ max_ndigits = 9; /* GET THIS */ { hwp = hw; } - multiplier = 1; - for (i = 0; i < max_ndigits; i++) multiplier *= radix; + STIX_ASSERT (ptr < end); do { r1 = 0; - for (dg = 0; dg < max_ndigits; dg++) + for (dg = 0; dg < safe_ndigits; dg++) { if (ptr >= end) { @@ -718,7 +738,7 @@ max_ndigits = 9; /* GET THIS */ } if (r2) hwp[hwlen++] = r2; } - while (dg >= max_ndigits); + while (ptr < end); } { int i; @@ -729,6 +749,7 @@ printf ("%08x ", hwp[--i]); printf ("\n"); } + STIX_ASSERT (hwlen > 1); if (hwlen == 1) return STIX_OOP_FROM_SMINT((stix_ooi_t)hwp[0] * -neg); else if (hwlen == 2) { @@ -752,3 +773,8 @@ oops_einval: stix->errnum = STIX_EINVAL; return STIX_NULL; } + +stix_oop_t stix_inttostr (stix_t* stix, stix_oop_t num) +{ + return STIX_NULL; +} diff --git a/stix/lib/main.c b/stix/lib/main.c index f67a899..0f88a44 100644 --- a/stix/lib/main.c +++ b/stix/lib/main.c @@ -467,7 +467,10 @@ int main (int argc, char* argv[]) /*const stix_bch_t* xxx = "9999999999999999999999999999999999999999999999999999999999999999999999999999999999";*/ //const stix_bch_t* xxx = "2305843009213693953"; -const stix_bch_t* xxx = "184467440737095516161111"; +//const stix_bch_t* xxx = "184467440737095516161111"; +const stix_bch_t* xxx = "999999999999999999999999"; +const stix_bch_t* yyy = "1000000000000000000000000000000000000000000000000"; +//const stix_bch_t* yyy = "1290812390812903812903812903812903812903481290381209381290381290381290831290381290381290831209381293712897361287361278631278361278631278631287361278361278"; stix_ooch_t buf[10240]; stix_oow_t xxxlen; @@ -476,7 +479,12 @@ stix_oow_t buflen; xxxlen = stix_countbcstr(xxx); buflen = STIX_COUNTOF(buf); stix_utf8toucs (xxx, &xxxlen, buf, &buflen); -dump_object (stix, stix_strtoint (stix, buf, buflen, 16), "STRINT"); +dump_object (stix, stix_strtoint (stix, buf, buflen, 10), "STRINT"); + +xxxlen = stix_countbcstr(yyy); +buflen = STIX_COUNTOF(buf); +stix_utf8toucs (yyy, &xxxlen, buf, &buflen); +dump_object (stix, stix_strtoint (stix, buf, buflen, 3), "STRINT"); } { stix_ooch_t x[] = { 'X', 't', 'r', 'i', 'n', 'g', '\0' }; diff --git a/stix/lib/stix-cfg.h.in b/stix/lib/stix-cfg.h.in index c67bfdb..4e67c02 100644 --- a/stix/lib/stix-cfg.h.in +++ b/stix/lib/stix-cfg.h.in @@ -772,6 +772,18 @@ /* Define to 1 if you have the `_vsnwprintf' function. */ #undef HAVE__VSNWPRINTF +/* __builtin_memcmp */ +#undef HAVE___BUILTIN_MEMCMP + +/* __builtin_memcpy */ +#undef HAVE___BUILTIN_MEMCPY + +/* __builtin_memmove */ +#undef HAVE___BUILTIN_MEMMOVE + +/* __builtin_memset */ +#undef HAVE___BUILTIN_MEMSET + /* __va_copy is available */ #undef HAVE___VA_COPY diff --git a/stix/lib/stix-cmn.h b/stix/lib/stix-cmn.h index cb38cc7..4393e94 100644 --- a/stix/lib/stix-cmn.h +++ b/stix/lib/stix-cmn.h @@ -195,8 +195,13 @@ #elif defined(STIX_SIZEOF___INT128_T) && (STIX_SIZEOF___INT128_T == 16) # define STIX_HAVE_UINT128_T # define STIX_HAVE_INT128_T + #if defined(__clang__) + typedef __uint128_t stix_uint128_t; + typedef __int128_t stix_int128_t; + #else typedef unsigned __int128_t stix_uint128_t; typedef signed __int128_t stix_int128_t; + #endif #else /* no 128-bit integer */ #endif diff --git a/stix/lib/stix-prv.h b/stix/lib/stix-prv.h index e6bf81e..c02d7c2 100644 --- a/stix/lib/stix-prv.h +++ b/stix/lib/stix-prv.h @@ -58,10 +58,42 @@ #include #include -#define STIX_MEMSET(dst,src,size) memset(dst,src,size) -#define STIX_MEMCPY(dst,src,size) memcpy(dst,src,size) -#define STIX_MEMMOVE(dst,src,size) memmove(dst,src,size) -#define STIX_MEMCMP(dst,src,size) memcmp(dst,src,size) +#if defined(__has_builtin) +# if __has_builtin(__builtin_memset) +# define STIX_MEMSET(dst,src,size) __builtin_memset(dst,src,size) +# else +# define STIX_MEMSET(dst,src,size) memset(dst,src,size) +# endif +# if __has_builtin(__builtin_memcpy) +# define STIX_MEMCPY(dst,src,size) __builtin_memcpy(dst,src,size) +# else +# define STIX_MEMCPY(dst,src,size) memcpy(dst,src,size) +# endif +# if __has_builtin(__builtin_memmove) +# define STIX_MEMMOVE(dst,src,size) __builtin_memmove(dst,src,size) +# else +# define STIX_MEMMOVE(dst,src,size) memmove(dst,src,size) +# endif +# if __has_builtin(__builtin_memcmp) +# define STIX_MEMCMP(dst,src,size) __builtin_memcmp(dst,src,size) +# else +# define STIX_MEMCMP(dst,src,size) memcmp(dst,src,size) +# endif + +#elif defined(__GNUC__) +/* TODO: may need to check a gnuc version or use autoconf to check the availibility ? */ +# define STIX_MEMSET(dst,src,size) __builtin_memset(dst,src,size) +# define STIX_MEMCPY(dst,src,size) __builtin_memcpy(dst,src,size) +# define STIX_MEMMOVE(dst,src,size) __builtin_memmove(dst,src,size) +# define STIX_MEMCMP(dst,src,size) __builtin_memcmp(dst,src,size) + +#else +# define STIX_MEMSET(dst,src,size) memset(dst,src,size) +# define STIX_MEMCPY(dst,src,size) memcpy(dst,src,size) +# define STIX_MEMMOVE(dst,src,size) memmove(dst,src,size) +# define STIX_MEMCMP(dst,src,size) memcmp(dst,src,size) +#endif + #define STIX_ASSERT(x) assert(x) #define STIX_ALIGN(x,y) ((((x) + (y) - 1) / (y)) * (y)) diff --git a/stix/lib/stix.h b/stix/lib/stix.h index 266640a..ee4cab3 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -699,6 +699,14 @@ struct stix_t stix_ooi_t ip; /* == END EXECUTION REGISTERS == */ + /* == BIGINT CONVERSION == */ + struct + { + int safe_ndigits; + stix_oow_t multiplier; + } bigint[36]; + /* == END BIGINT CONVERSION == */ + #if defined(STIX_INCLUDE_COMPILER) stix_compiler_t* c; #endif