[ create a new paste ] login | about

Link: http://codepad.org/7wx4aW0Y    [ raw code | output | fork ]

runnig - C++, pasted on Dec 4:
#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;
}


Output:
1
2
3
4
5
6
7
8
Line 19: error: intrin.h: No such file or directory
cc1plus: warnings being treated as errors
In function 'int test(int (*)(char*), char*)':
Line 124: warning: format '%d' expects type 'int', but argument 3 has type 'long int'
In function 'int main(int, char**)':
Line 153: warning: deprecated conversion from string constant to 'char*''
Line 154: warning: deprecated conversion from string constant to 'char*''
Line 155: warning: deprecated conversion from string constant to 'char*''


Create a new paste based on this one


Comments: