Created
July 7, 2013 12:59
-
-
Save mechanicker/5943399 to your computer and use it in GitHub Desktop.
Optimizing strong compare
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Time-stamp: <2013-07-07 10:37:24 dky> */ | |
#include <stdio.h> | |
#include <string.h> | |
int stringcompare(const char*, const char*); | |
int stringcompareopt(const char *, size_t, const char *, size_t); | |
int stringcompare(const char *s1, const char *s2) { | |
size_t idx = 0; | |
int ret = 0; | |
if (s1 == s2) { | |
return 0; | |
} else if (NULL == s2) { | |
return 1; | |
} else if (NULL == s1) { | |
return -1; | |
} | |
/* Consider loop unrolling if string lenghts are known */ | |
for (idx = 0; s1[idx] && s2[idx]; ++idx) { | |
if (s1[idx] < s2[idx]) { | |
ret = -1; | |
break; | |
} else if (s1[idx] > s2[idx]) { | |
ret = 1; | |
break; | |
} | |
} | |
if (0 == ret) { | |
/* Check if there is still data in the strings */ | |
if (s1[idx]) { | |
ret = 1; | |
} else if (s2[idx]) { | |
ret = -1; | |
} | |
} | |
return ret; | |
} | |
int stringcompareopt(const char *s1, size_t l1, const char *s2, size_t l2) { | |
if (s1 == s2) { | |
return 0; | |
} else if (0 == l1 && 0 == l2) { | |
return 0; | |
} else if (NULL == s2) { | |
return 1; | |
} else if (NULL == s1) { | |
return -1; | |
} | |
/* Both strings are non zero length and have the same length */ | |
size_t idx = 0; | |
size_t min = (l1 < l2) ? l1 : l2; | |
while (min - idx) { | |
if (sizeof(size_t) > (min - idx)) { | |
if (s1[idx] < s2[idx]) { | |
return -1; | |
} else if (s1[idx] > s2[idx]) { | |
return 1; | |
} | |
++idx; | |
} else { /* Loop unrolling */ | |
size_t *u1 = (size_t *)(s1 + idx), | |
*u2 = (size_t *)(s2 + idx); | |
if (*u1 < *u2) { | |
return -1; | |
} else if (*u1 > *u2) { | |
return 1; | |
} | |
idx += sizeof(size_t); | |
} | |
} | |
int ret = l1 - l2; | |
if (ret < 0) { | |
ret = -1; | |
} else if (ret > 0) { | |
ret = 1; | |
} | |
return ret; | |
} | |
int main(int argc, char *argv[]) { | |
if (argc < 3) { | |
fprintf(stderr, "Usage: %s string1 string2\n", argv[0]); | |
return -1; | |
} | |
/* Use the library function to check for correctness */ | |
printf("Comparing using strcmp: %d\n", strcmp(argv[1], argv[2])); | |
/* Byte-wise comparison */ | |
printf("Comparing using stringcompare: %d\n", stringcompare(argv[1], | |
argv[2])); | |
/* If the string length is known: Unroll the loop */ | |
printf("Comparing using stringcompareopt: %d\n", | |
stringcompareopt(argv[1], strlen(argv[1]), | |
argv[2], strlen(argv[2]))); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment