gh-121562: optimized hex_from_char (#121563)

Performance improvement to `float.fromhex`: use a lookup table
for computing the hexadecimal value of a character, in place of the
previous switch-case construct. Patch by Bruno Lima.
This commit is contained in:
Bruno Lima 2024-07-14 06:05:35 -03:00 committed by GitHub
parent f6f4022a35
commit 04130b290b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 62 deletions

View File

@ -0,0 +1,2 @@
Optimized performance of hex_from_char by replacing switch-case with a
lookup table

View File

@ -1142,69 +1142,39 @@ char_from_hex(int x)
return Py_hexdigits[x]; return Py_hexdigits[x];
} }
/* This table maps characters to their hexadecimal values, only
* works with encodings whose lower half is ASCII (like UTF-8).
* '0' maps to 0, ..., '9' maps to 9.
* 'a' and 'A' map to 10, ..., 'f' and 'F' map to 15.
* All other indices map to -1.
*/
static const int
_CHAR_TO_HEX[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
/* Convert a character to its hexadecimal value, or -1 if it's not a
* valid hexadecimal character, only works with encodings whose lower
* half is ASCII (like UTF-8).
*/
static int static int
hex_from_char(char c) { hex_from_char(unsigned char c) {
int x; return _CHAR_TO_HEX[c];
switch(c) {
case '0':
x = 0;
break;
case '1':
x = 1;
break;
case '2':
x = 2;
break;
case '3':
x = 3;
break;
case '4':
x = 4;
break;
case '5':
x = 5;
break;
case '6':
x = 6;
break;
case '7':
x = 7;
break;
case '8':
x = 8;
break;
case '9':
x = 9;
break;
case 'a':
case 'A':
x = 10;
break;
case 'b':
case 'B':
x = 11;
break;
case 'c':
case 'C':
x = 12;
break;
case 'd':
case 'D':
x = 13;
break;
case 'e':
case 'E':
x = 14;
break;
case 'f':
case 'F':
x = 15;
break;
default:
x = -1;
break;
}
return x;
} }
/* convert a float to a hexadecimal string */ /* convert a float to a hexadecimal string */