From 1bd422a6c117515fb965cb35e2e1fd3cb04e895e Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 04:01:40 -0500 Subject: [PATCH 01/10] fast compute of _all_zeroes function --- Lib/_pydecimal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index ec036199331396..cb7fe440a23fbc 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6076,7 +6076,10 @@ def _convert_for_comparison(self, other, equality_op=False): \Z """, re.VERBOSE | re.IGNORECASE).match -_all_zeros = re.compile('0*$').match +# Checks for regex 0*$ +def _all_zeros(d_int,prec=0): + return '0' in d_int and d_int.endswith((len(d_int) - prec) * '0') + _exact_half = re.compile('50*$').match ##### PEP3101 support functions ############################################## From d5e634ca5186d1ba6d3eef22f7b65c3002673a1f Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 04:07:23 -0500 Subject: [PATCH 02/10] Added news --- .../next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst diff --git a/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst b/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst new file mode 100644 index 00000000000000..4de49ac79aeff7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst @@ -0,0 +1,2 @@ +Improved performance of :func:`_pydecimal._all_zeros` by an average of +~1.7x. Patch by Marius Juston From 7037f19adfe276af541536f63705b8f870010c8e Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 04:20:53 -0500 Subject: [PATCH 03/10] speed up for exact half --- Lib/_pydecimal.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index cb7fe440a23fbc..8035b1804dfee0 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6080,7 +6080,9 @@ def _convert_for_comparison(self, other, equality_op=False): def _all_zeros(d_int,prec=0): return '0' in d_int and d_int.endswith((len(d_int) - prec) * '0') -_exact_half = re.compile('50*$').match +# Checks for regex 50*$ +def _exact_half(d_int, prec=0): + return len(d_int) >= prec and d_int[prec - 1] == '5' and d_int.endswith(max(len(d_int) - prec - 1, 0) * '0') ##### PEP3101 support functions ############################################## # The functions in this section have little to do with the Decimal From 1b34a8928d03d30d1252e7cd928dab1095c11d86 Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 04:22:33 -0500 Subject: [PATCH 04/10] updated news --- .../next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst b/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst index 4de49ac79aeff7..11b501237eb25d 100644 --- a/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst +++ b/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst @@ -1,2 +1,2 @@ Improved performance of :func:`_pydecimal._all_zeros` by an average of -~1.7x. Patch by Marius Juston +~1.7x and :func:`_pydecimal._exact_half` by ~1.27x. Patch by Marius Juston From c498ae6d96c3e942144f573e5e7b31ac5874ff77 Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 04:41:45 -0500 Subject: [PATCH 05/10] corrected indexing checks for exact half --- Lib/_pydecimal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 8035b1804dfee0..7505e1cb7b725b 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6082,7 +6082,7 @@ def _all_zeros(d_int,prec=0): # Checks for regex 50*$ def _exact_half(d_int, prec=0): - return len(d_int) >= prec and d_int[prec - 1] == '5' and d_int.endswith(max(len(d_int) - prec - 1, 0) * '0') + return len(d_int) >= prec + 1 and d_int[prec] == '5' and d_int.endswith(max(len(d_int) - prec - 1, 0) * '0') ##### PEP3101 support functions ############################################## # The functions in this section have little to do with the Decimal From 328c99be00072a3f990a2b6be614b47cafff43c9 Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 04:52:06 -0500 Subject: [PATCH 06/10] update news performance value --- .../next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst b/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst index 11b501237eb25d..631a89ccfd1bc2 100644 --- a/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst +++ b/Misc/NEWS.d/next/Library/2025-04-04-04-07-16.gh-issue-130167.XigAlq.rst @@ -1,2 +1,2 @@ Improved performance of :func:`_pydecimal._all_zeros` by an average of -~1.7x and :func:`_pydecimal._exact_half` by ~1.27x. Patch by Marius Juston +~1.7x and :func:`_pydecimal._exact_half` by ~1.38x. Patch by Marius Juston From b6a801497df192a7b5601594172e882c644e1708 Mon Sep 17 00:00:00 2001 From: Marius Juston Date: Fri, 4 Apr 2025 07:03:28 -0500 Subject: [PATCH 07/10] Update Lib/_pydecimal.py Co-authored-by: Pieter Eendebak --- Lib/_pydecimal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 7505e1cb7b725b..c4e9c23b54b29e 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6077,7 +6077,7 @@ def _convert_for_comparison(self, other, equality_op=False): """, re.VERBOSE | re.IGNORECASE).match # Checks for regex 0*$ -def _all_zeros(d_int,prec=0): +def _all_zeros(d_int, prec=0): return '0' in d_int and d_int.endswith((len(d_int) - prec) * '0') # Checks for regex 50*$ From 027d93da7e95888b730613a7973a2c750258b12a Mon Sep 17 00:00:00 2001 From: Marius Juston Date: Fri, 4 Apr 2025 07:04:17 -0500 Subject: [PATCH 08/10] Update Lib/_pydecimal.py Co-authored-by: Pieter Eendebak --- Lib/_pydecimal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index c4e9c23b54b29e..afd209de462de3 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6082,7 +6082,7 @@ def _all_zeros(d_int, prec=0): # Checks for regex 50*$ def _exact_half(d_int, prec=0): - return len(d_int) >= prec + 1 and d_int[prec] == '5' and d_int.endswith(max(len(d_int) - prec - 1, 0) * '0') + return len(d_int) >= prec + 1 and d_int[prec] == '5' and d_int.endswith( (len(d_int) - prec - 1) * '0') ##### PEP3101 support functions ############################################## # The functions in this section have little to do with the Decimal From 34486ddd5d1dad061cb7bbb44c761cbdf0a27c48 Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 07:20:26 -0500 Subject: [PATCH 09/10] simplified and sped up _all_zeros compute --- Lib/_pydecimal.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index afd209de462de3..1dc8cc4d36d506 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6078,7 +6078,14 @@ def _convert_for_comparison(self, other, equality_op=False): # Checks for regex 0*$ def _all_zeros(d_int, prec=0): - return '0' in d_int and d_int.endswith((len(d_int) - prec) * '0') + i = prec + len_d = len(d_int) + + while i < len_d: + if d_int[i] != '0': + return False + i += 1 + return True # Checks for regex 50*$ def _exact_half(d_int, prec=0): From faae133bbd3773f1686fcb909593b6f75a32eddd Mon Sep 17 00:00:00 2001 From: Marius-Juston Date: Fri, 4 Apr 2025 07:28:16 -0500 Subject: [PATCH 10/10] simplified and sped up exact_half --- Lib/_pydecimal.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 1dc8cc4d36d506..dc55fdfa3c8dd1 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -6089,7 +6089,16 @@ def _all_zeros(d_int, prec=0): # Checks for regex 50*$ def _exact_half(d_int, prec=0): - return len(d_int) >= prec + 1 and d_int[prec] == '5' and d_int.endswith( (len(d_int) - prec - 1) * '0') + len_d = len(d_int) + i = prec + 1 + + if len_d >= i and d_int[prec] == '5': + while i < len_d: + if d_int[i] != '0': + return False + i += 1 + return True + return False ##### PEP3101 support functions ############################################## # The functions in this section have little to do with the Decimal