#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <intrin.h>
#include <stdio.h>
int search1_no_strlen(char *str){
char ch;
for (char *p = str; 0 != (ch = *p); ++p)
{
if ( ch >= '0' && ch <= '9')
return p-str;
}
return (-1);
}
int search1(char *str){
int l=0;
int i;
l = strlen(str);
for (i=0;i<l;i++){
if ((str[i] >= '0') && (str[i] <= '9')){
return (i);
}
}
return (-1);
}
int search3( char *str){
int n, j = 0;
unsigned x, y, *r;
const char *c_ptr;
//Проверяем посимвольно первые байты, пока не выровняем.
for (c_ptr=str; ((unsigned long int)c_ptr & (sizeof(x) - 1)) != 0; ++c_ptr)
if ((*c_ptr >= '0') && (*c_ptr <= '9'))
return c_ptr - str;
r = (unsigned *) c_ptr;
j = c_ptr - str ;
while (1){
x = *r ^ 0x30303030;
y = (x & 0x7F7F7F7F) + 0x76767676;
y = ~(y | x | 0x7F7F7F7F);
// These steps map:
if (y == 0) n = 4; // 00000000 ==> 4,
else if (y > 0x0000FFFF) // 80xxxxxx ==> 0,
n= (y >> 31) ^ 1; // 0080xxxx ==> 1,
else // 000080xx ==> 2,
n= (y >> 15) ^ 3; // 00000080 ==> 3.
j=j+n ;
if (n<4) {j =j +3 -2*n; break;}
r++;
}
return (j);
}
#ifdef WIN32
int find_digit(char* str) {
static const __m128i str_mask[16] = {
_mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00FFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x000000FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00FFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x000000FF, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x00FFFFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x0000FFFF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x000000FF, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x00000000, 0x00FFFFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x00000000, 0x0000FFFF),
_mm_set_epi32(0x00000000, 0x00000000, 0x00000000, 0x000000FF)
};
static const __m128i str_offset = _mm_set1_epi8(127 - '9');
static const __m128i str_threshold = _mm_set1_epi8(127 - 10);
const size_t str_misalignment = ((size_t)str) & ((size_t)15);
const __m128i* str_aligned = (const __m128i*)(((size_t)str) - str_misalignment);
__m128i str_vector = _mm_load_si128(str_aligned);
str_vector = _mm_and_si128(str_vector, str_mask[str_misalignment]);
str_vector = _mm_add_epi8(str_vector, str_offset);
int str_bitmask = _mm_movemask_epi8(_mm_cmpgt_epi8(str_vector, str_threshold));
unsigned long index;
_BitScanForward(&index, str_bitmask);
while (str_bitmask == 0) {
str_aligned += 1;
str_vector = _mm_load_si128(str_aligned);
str_vector = _mm_add_epi8(str_vector, str_offset);
str_bitmask = _mm_movemask_epi8(_mm_cmpgt_epi8(str_vector, str_threshold));
_BitScanForward(&index, str_bitmask);
}
return (((char*)str_aligned) + index)-str;
}
#endif
const int MAX_STRINGS = 1024;
const int MAX_LEN = 1024;
const int MAX_TESTS = MAX_STRINGS * 1000;
char strings[MAX_STRINGS][MAX_LEN];
typedef int (*search_fn)(char *);
int test(search_fn search, char *fn_name)
{
clock_t start = clock();
int pos = 0;
for(int t = 0; t < MAX_TESTS; ++t)
{
pos += search(strings[t % MAX_STRINGS]);
}
printf("%s %d\n", fn_name, clock() - start);
return pos;
}
int main(int argc, char* argv[])
{
srand(0);
for(int i=0; i<MAX_STRINGS; ++i)
{
char * s = strings[i];
int len = rand() % MAX_LEN;
s[len] = 0;
if(len > 0)
{
int digit_pos = rand() % len;
for(int j = 0; j < len; ++j)
{
if(j < digit_pos)
s[j] = rand() % ('z'-'a') + 'a';
else
s[j] = rand() % ('9'-'0') + '0';
}
}
}
int res[4] = {0,0,0,0};
res[0] = test(search1, "search1");
res[1] = test(search1_no_strlen, "search1_no_strlen");
res[2] = test(search3, "search3");
#ifdef WIN32
res[3] = test(find_digit, "find_digit");
#endif
printf("%d %d %d %d\n", res[0], res[1], res[2], res[3]);
return 0;
}