summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Lima <bdl1998@hotmail.com>2024-07-14 09:05:35 (GMT)
committerGitHub <noreply@github.com>2024-07-14 09:05:35 (GMT)
commit04130b290b545e64625c07dc8fa2709d17e70880 (patch)
tree1d748d0be64a86c777a02e46188c3606c1ca9953
parentf6f4022a357f70f1c40945403065e81b6c2e4854 (diff)
downloadcpython-04130b290b545e64625c07dc8fa2709d17e70880.zip
cpython-04130b290b545e64625c07dc8fa2709d17e70880.tar.gz
cpython-04130b290b545e64625c07dc8fa2709d17e70880.tar.bz2
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.
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-07-10-02-02-32.gh-issue-121562.8beIMi.rst2
-rw-r--r--Objects/floatobject.c94
2 files changed, 34 insertions, 62 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-07-10-02-02-32.gh-issue-121562.8beIMi.rst b/Misc/NEWS.d/next/Core and Builtins/2024-07-10-02-02-32.gh-issue-121562.8beIMi.rst
new file mode 100644
index 0000000..9403809
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-07-10-02-02-32.gh-issue-121562.8beIMi.rst
@@ -0,0 +1,2 @@
+Optimized performance of hex_from_char by replacing switch-case with a
+lookup table
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 2627ba8..31f4145 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1142,69 +1142,39 @@ char_from_hex(int 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
-hex_from_char(char c) {
- int x;
- 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;
+hex_from_char(unsigned char c) {
+ return _CHAR_TO_HEX[c];
}
/* convert a float to a hexadecimal string */