読者です 読者をやめる 読者になる 読者になる

Search Non ASCII with words

通常上のようなケースではベクトル化されないので自分でやります。具体的にはバイト列を 1 バイトごと調べていたのを、ワード単位で判定するようにします。アライメントを揃えないと落ちたり遅くなったりするので前処理と、端数対策で後処理を。これで 1000 文字を 100 万回調べるのに 2.5 秒と、大幅な高速化が可能になります。(これが akr さんの r15129 の変更)

#if SIZEOF_VOIDP == 8
# define NONASCII_MASK 0x8080808080808080LL
#elif SIZEOF_VOIDP == 4
# define NONASCII_MASK 0x80808080UL
#endif

const char *
search_nonascii_words(const char *p, const char *e)
{
    intptr_t align;
    if (SIZEOF_VOIDP * 2 <= e - p) {
	const intptr_t lowbits = SIZEOF_VOIDP - 1;
	const intptr_t *wp, *we;
	align = (intptr_t)p & (SIZEOF_VOIDP - 1);
	switch (align) {
#if SIZEOF_VOIDP == 8
	case 7: if (!isascii(*p)) return p; ++p;
	case 6: if (!isascii(*p)) return p; ++p;
	case 5: if (!isascii(*p)) return p; ++p;
	case 4: if (!isascii(*p)) return p; ++p;
#endif
	case 3: if (!isascii(*p)) return p; ++p;
	case 2: if (!isascii(*p)) return p; ++p;
	case 1: if (!isascii(*p)) return p; ++p;
	}
	wp = (const intptr_t *)(~lowbits & ((intptr_t)p + lowbits));
	we = (const intptr_t *)(~lowbits & (intptr_t)e);
	for (; wp < we; ++wp) {
	    if (*wp & NONASCII_MASK) break;
	}
	p = (const char *)wp;
	switch (e - p) {
#if SIZEOF_VOIDP == 8
	case 7: if (!isascii(*p)) return p; ++p;
	case 6: if (!isascii(*p)) return p; ++p;
	case 5: if (!isascii(*p)) return p; ++p;
	case 4: if (!isascii(*p)) return p; ++p;
#endif
	case 3: if (!isascii(*p)) return p; ++p;
	case 2: if (!isascii(*p)) return p; ++p;
	case 1: if (!isascii(*p)) return p; ++p;
	}
    }
    else {
	switch (e - p) {
#if SIZEOF_VOIDP == 8
	case 15: if (!isascii(*p)) return p; ++p;
	case 14: if (!isascii(*p)) return p; ++p;
	case 13: if (!isascii(*p)) return p; ++p;
	case 12: if (!isascii(*p)) return p; ++p;
	case 11: if (!isascii(*p)) return p; ++p;
	case 10: if (!isascii(*p)) return p; ++p;
	case 9: if (!isascii(*p)) return p; ++p;
	case 8: if (!isascii(*p)) return p; ++p;
#endif
	case 7: if (!isascii(*p)) return p; ++p;
	case 6: if (!isascii(*p)) return p; ++p;
	case 5: if (!isascii(*p)) return p; ++p;
	case 4: if (!isascii(*p)) return p; ++p;
	case 3: if (!isascii(*p)) return p; ++p;
	case 2: if (!isascii(*p)) return p; ++p;
	case 1: if (!isascii(*p)) return p;
	}
	return NULL;
    }
}