From b166754b253eb41cb3bffd6071937a719acafd19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Wed, 5 Apr 2023 10:43:59 -0300 Subject: [PATCH 1/3] Fix construction functor for p-adic relaxed types. The precision for relaxed p-adics has 3 components: `(default_prec, halting_prec, secure)` where the last one `secure` is a boolean defaulting to `False`. However, the `construction()` method doesn't know about it: ``` sage: K = QpER(5, secure=True) sage: K.construction(forbid_frac_field=True) (Completion[5, prec=(20, 40)], Rational Field) sage: R = ZpER(5, secure=True) sage: R.construction() (Completion[5, prec=(20, 40)], Integer Ring) ``` This has two undesired consequences for the `change()` method: a. The `secure` attribute is not copied: ``` sage: K.is_secure() True sage: K.change().is_secure() False sage: R.is_secure() True sage: R.change().is_secure() False ``` b. The `check=False` option is broken: ``` sage: K.change(check=False) ... ValueError: not enough values to unpack (expected 3, got 2) sage: R.change(check=False) ... ValueError: not enough values to unpack (expected 3, got 2) ``` Fixing the `construction()` method solves both issues. After this commit: ``` sage: K = QpER(5, secure=True) sage: K.construction(forbid_frac_field=True) (Completion[5, prec=(20, 40, True)], Rational Field) sage: K.change().is_secure() True sage: K.change(check=False) 5-adic Field handled with relaxed arithmetics sage: K.change(check=False).is_secure() True sage: R = ZpER(5, secure=True) sage: R.construction() (Completion[5, prec=(20, 40, True)], Integer Ring) sage: R.change().is_secure() True sage: R.change(check=False) 5-adic Ring handled with relaxed arithmetics sage: R.change(check=False).is_secure() True ``` --- src/sage/rings/padics/generic_nodes.py | 16 ++++++++++++++-- src/sage/rings/padics/local_generic.py | 19 +++++++++++++++++++ src/sage/rings/padics/padic_generic.py | 6 ++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/padics/generic_nodes.py b/src/sage/rings/padics/generic_nodes.py index 3c5d9c2aaf5..6d666302d27 100644 --- a/src/sage/rings/padics/generic_nodes.py +++ b/src/sage/rings/padics/generic_nodes.py @@ -1423,13 +1423,19 @@ def construction(self, forbid_frac_field=False): sage: S = F(Z) sage: S._precision_cap() (31, 41) + + The `secure` attribute for relaxed type is included in the functor:: + + sage: R = ZpER(5, secure=True) + sage: R.construction() + (Completion[5, prec=(20, 40, True)], Integer Ring) """ from sage.categories.pushout import CompletionFunctor extras = {'print_mode':self._printer.dict(), 'type':self._prec_type(), 'names':self._names} if hasattr(self, '_label'): extras['label'] = self._label if self._prec_type() == "relaxed": - prec = (self._default_prec, self._halting_prec) + prec = (self._default_prec, self._halting_prec, self._secure) else: prec = self._precision_cap() return (CompletionFunctor(self.prime(), prec, extras), ZZ) @@ -1595,6 +1601,12 @@ def construction(self, forbid_frac_field=False): sage: S = F(Z) sage: S._precision_cap() (31, 41) + + The `secure` attribute for relaxed type is included in the functor:: + + sage: K = QpER(5, secure=True) + sage: K.construction(forbid_frac_field=True) + (Completion[5, prec=(20, 40, True)], Rational Field) """ from sage.categories.pushout import FractionField, CompletionFunctor if forbid_frac_field: @@ -1602,7 +1614,7 @@ def construction(self, forbid_frac_field=False): if hasattr(self, '_label'): extras['label'] = self._label if self._prec_type() == "relaxed": - prec = (self._default_prec, self._halting_prec) + prec = (self._default_prec, self._halting_prec, self._secure) else: prec = self._precision_cap() return (CompletionFunctor(self.prime(), prec, extras), QQ) diff --git a/src/sage/rings/padics/local_generic.py b/src/sage/rings/padics/local_generic.py index 2168d2e348b..df8487c609d 100644 --- a/src/sage/rings/padics/local_generic.py +++ b/src/sage/rings/padics/local_generic.py @@ -375,6 +375,25 @@ def change(self, **kwds): 37-adic Ring with lattice-cap precision (label: change) sage: S.change(label = "new") 37-adic Ring with lattice-cap precision (label: new) + + + TESTS: + + The `secure` attribute for relaxed type is copied:: + + sage: R = ZpER(5, secure=True); R + 5-adic Ring handled with relaxed arithmetics + sage: K = R.change(field=True); K + 5-adic Field handled with relaxed arithmetics + sage: K.is_secure() + True + + The `check=False` option works for relaxed type:: + + sage: R = ZpER(5) ; R + 5-adic Ring handled with relaxed arithmetics + sage: K = R.change(field=True, check=False) ; K + 5-adic Field handled with relaxed arithmetics """ # We support both print_* and * for *=mode, pos, sep, alphabet for atr in ('print_mode', 'print_pos', 'print_sep', 'print_alphabet'): diff --git a/src/sage/rings/padics/padic_generic.py b/src/sage/rings/padics/padic_generic.py index 2f9c2195720..56ee6610d0d 100644 --- a/src/sage/rings/padics/padic_generic.py +++ b/src/sage/rings/padics/padic_generic.py @@ -478,6 +478,12 @@ def integer_ring(self, print_mode=None): 2-adic Ring with lattice-cap precision (label: test) sage: R.integer_ring({'mode':'series'}) is R True + + The `secure` attribute for relaxed type is preserved:: + + sage: K = QpER(5, secure=True) + sage: K.integer_ring().is_secure() + True """ # Currently does not support fields with non integral defining # polynomials. This should change when the padic_general_extension From 1d0a04a6958eda4dea923b2fe6615c7086ce5f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Thu, 6 Apr 2023 14:06:45 -0300 Subject: [PATCH 2/3] Run TestSuite for padic relaxed types with secure=True --- src/sage/rings/padics/padic_base_leaves.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/rings/padics/padic_base_leaves.py b/src/sage/rings/padics/padic_base_leaves.py index 7963a442f97..3c382fd292b 100644 --- a/src/sage/rings/padics/padic_base_leaves.py +++ b/src/sage/rings/padics/padic_base_leaves.py @@ -1128,6 +1128,8 @@ def __init__(self, p, prec, print_mode, names): sage: R = ZpER(7) sage: TestSuite(R).run(skip=['_test_log', '_test_matrix_smith']) + sage: R = ZpER(7, secure=True) + sage: TestSuite(R).run(skip=['_test_log', '_test_matrix_smith']) """ from sage.rings.padics import padic_relaxed_element self._default_prec, self._halting_prec, self._secure = prec @@ -1163,6 +1165,8 @@ def __init__(self, p, prec, print_mode, names): sage: K = QpER(7) sage: TestSuite(K).run(skip=['_test_log', '_test_matrix_smith']) + sage: K = QpER(7, secure=True) + sage: TestSuite(K).run(skip=['_test_log', '_test_matrix_smith']) """ from sage.rings.padics import padic_relaxed_element self._default_prec, self._halting_prec, self._secure = prec From 18d6640d8b9e4586094b88588fb3f401d10b7bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= Date: Mon, 27 Feb 2023 15:19:47 -0300 Subject: [PATCH 3/3] Make Qp.integer_ring() faster. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The method pAdicGeneric.integer_ring() uses LocalGeneric.change() to turn a p-adic field into a p-adic ring. The latter calls a factory function which, by default, checks primality of p. However, when p came from a Qp this step is not necessary. We avoid it by adding `check=False` to the call to `LocalGeneric.change()` in `pAdicGeneric.integer_ring()`. This results in significant time savings for large primes, e.g. in the current test suite: Before this commit: ``` sage: R = Qp(next_prime(10^60)) sage: timeit('R.integer_ring()') 25 loops, best of 3: 22.2 ms per loop sage: %time TestSuite(R).run() CPU times: user 14.4 s, sys: 44 µs, total: 14.4 s Wall time: 14.4 s ``` After this commit: ``` sage: R = Qp(next_prime(10^60)) sage: timeit('R.integer_ring()') 625 loops, best of 3: 68 μs per loop sage: %time TestSuite(R).run() CPU times: user 714 ms, sys: 239 µs, total: 715 ms Wall time: 717 ms ``` Doctest of `padic_base_leaves.py` goes down from ~33 to ~5 seconds. --- src/sage/rings/padics/padic_generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/padics/padic_generic.py b/src/sage/rings/padics/padic_generic.py index 56ee6610d0d..93756aeb772 100644 --- a/src/sage/rings/padics/padic_generic.py +++ b/src/sage/rings/padics/padic_generic.py @@ -491,7 +491,7 @@ def integer_ring(self, print_mode=None): if not self.is_field() and print_mode is None: return self if print_mode is None: - return self.change(field=False) + return self.change(field=False, check=False) else: from sage.misc.superseded import deprecation deprecation(23227, "Use the change method if you want to change print options in integer_ring()")