mirror of
https://github.com/php/php-src.git
synced 2024-11-27 03:44:07 +08:00
decbin/decoct/dechex optimization.
This commit is contained in:
parent
ec158c25c4
commit
aae50328e2
@ -75,6 +75,46 @@ static zend_always_inline int zend_ulong_ntz(zend_ulong num)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Number of leading zero bits (Undefined for zero) */
|
||||
static zend_always_inline int zend_ulong_nlz(zend_ulong num)
|
||||
{
|
||||
#if (defined(__GNUC__) || __has_builtin(__builtin_clzl)) \
|
||||
&& SIZEOF_ZEND_LONG == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CLZL)
|
||||
return __builtin_clzl(num);
|
||||
#elif (defined(__GNUC__) || __has_builtin(__builtin_clzll)) && defined(PHP_HAVE_BUILTIN_CLZLL)
|
||||
return __builtin_clzll(num);
|
||||
#elif defined(_WIN32)
|
||||
unsigned long index;
|
||||
|
||||
#if defined(_WIN64)
|
||||
if (!BitScanReverse64(&index, num)) {
|
||||
#else
|
||||
if (!BitScanReverse(&index, num)) {
|
||||
#endif
|
||||
/* undefined behavior */
|
||||
return SIZEOF_ZEND_LONG * 8;
|
||||
}
|
||||
|
||||
return (int) (SIZEOF_ZEND_LONG * 8 - 1)- index;
|
||||
#else
|
||||
zend_ulong x;
|
||||
int n;
|
||||
|
||||
#if SIZEOF_ZEND_LONG == 8
|
||||
n = 64;
|
||||
x = num >> 32; if (x != 0) {n -= 32; num = x;}
|
||||
#else
|
||||
n = 32;
|
||||
#endif
|
||||
x = num >> 16; if (x != 0) {n -= 16; num = x;}
|
||||
x = num >> 8; if (x != 0) {n -= 8; num = x;}
|
||||
x = num >> 4; if (x != 0) {n -= 4; num = x;}
|
||||
x = num >> 2; if (x != 0) {n -= 2; num = x;}
|
||||
x = num >> 1; if (x != 0) return n - 2;
|
||||
return n - num;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns the number of zend_ulong words needed to store a bitset that is N
|
||||
bits long. */
|
||||
static inline uint32_t zend_bitset_len(uint32_t n)
|
||||
|
38
build/php.m4
38
build/php.m4
@ -2448,6 +2448,44 @@ AC_DEFUN([PHP_CHECK_BUILTIN_CLZ], [
|
||||
AC_DEFINE_UNQUOTED([PHP_HAVE_BUILTIN_CLZ], [$have_builtin_clz], [Whether the compiler supports __builtin_clz])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl PHP_CHECK_BUILTIN_CLZL
|
||||
dnl
|
||||
AC_DEFUN([PHP_CHECK_BUILTIN_CLZL], [
|
||||
AC_MSG_CHECKING([for __builtin_clzl])
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[
|
||||
return __builtin_clzl(1) ? 1 : 0;
|
||||
]])], [
|
||||
have_builtin_clzl=1
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
have_builtin_clzl=0
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED([PHP_HAVE_BUILTIN_CLZL], [$have_builtin_clzl], [Whether the compiler supports __builtin_clzl])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl PHP_CHECK_BUILTIN_CLZLL
|
||||
dnl
|
||||
AC_DEFUN([PHP_CHECK_BUILTIN_CLZLL], [
|
||||
AC_MSG_CHECKING([for __builtin_clzll])
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[
|
||||
return __builtin_clzll(1) ? 1 : 0;
|
||||
]])], [
|
||||
have_builtin_clzll=1
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
have_builtin_clzll=0
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
AC_DEFINE_UNQUOTED([PHP_HAVE_BUILTIN_CLZLL], [$have_builtin_clzll], [Whether the compiler supports __builtin_clzll])
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl PHP_CHECK_BUILTIN_CTZL
|
||||
dnl
|
||||
|
@ -465,6 +465,10 @@ dnl Check __builtin_expect
|
||||
PHP_CHECK_BUILTIN_EXPECT
|
||||
dnl Check __builtin_clz
|
||||
PHP_CHECK_BUILTIN_CLZ
|
||||
dnl Check __builtin_clzl
|
||||
PHP_CHECK_BUILTIN_CLZL
|
||||
dnl Check __builtin_clzll
|
||||
PHP_CHECK_BUILTIN_CLZLL
|
||||
dnl Check __builtin_ctzl
|
||||
PHP_CHECK_BUILTIN_CTZL
|
||||
dnl Check __builtin_ctzll
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "zend_multiply.h"
|
||||
#include "zend_exceptions.h"
|
||||
#include "zend_portability.h"
|
||||
#include "zend_bitset.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
@ -821,6 +822,41 @@ PHPAPI zend_string * _php_math_longtobase(zend_long arg, int base)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _php_math_longtobase_pwr2 */
|
||||
/*
|
||||
* Convert a long to a string containing a base(2,4,6,16,32) representation of
|
||||
* the number.
|
||||
*/
|
||||
static zend_always_inline zend_string * _php_math_longtobase_pwr2(zend_long arg, int base_log2)
|
||||
{
|
||||
static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
zend_ulong value;
|
||||
size_t len;
|
||||
zend_string *ret;
|
||||
char *ptr;
|
||||
|
||||
value = arg;
|
||||
|
||||
if (value == 0) {
|
||||
len = 1;
|
||||
} else {
|
||||
len = ((sizeof(value) * 8 - zend_ulong_nlz(value)) + (base_log2 - 1)) / base_log2;
|
||||
}
|
||||
|
||||
ret = zend_string_alloc(len, 0);
|
||||
ptr = ZSTR_VAL(ret) + len;
|
||||
*ptr = '\0';
|
||||
|
||||
do {
|
||||
ZEND_ASSERT(ptr > ZSTR_VAL(ret));
|
||||
*--ptr = digits[value & ((1 << base_log2) - 1)];
|
||||
value >>= base_log2;
|
||||
} while (value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _php_math_zvaltobase */
|
||||
/*
|
||||
* Convert a zval to a string containing a base(2-36) representation of
|
||||
@ -908,7 +944,7 @@ PHP_FUNCTION(decbin)
|
||||
Z_PARAM_LONG(arg)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
RETURN_STR(_php_math_longtobase(arg, 2));
|
||||
RETURN_STR(_php_math_longtobase_pwr2(arg, 1));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -921,7 +957,7 @@ PHP_FUNCTION(decoct)
|
||||
Z_PARAM_LONG(arg)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
RETURN_STR(_php_math_longtobase(arg, 8));
|
||||
RETURN_STR(_php_math_longtobase_pwr2(arg, 3));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -934,7 +970,7 @@ PHP_FUNCTION(dechex)
|
||||
Z_PARAM_LONG(arg)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
RETURN_STR(_php_math_longtobase(arg, 16));
|
||||
RETURN_STR(_php_math_longtobase_pwr2(arg, 4));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user