Skip to content

Commit 66e5d69

Browse files
author
Xavier Caruso
committed
improve intersection/union and remove in_range
1 parent dcc0f16 commit 66e5d69

File tree

1 file changed

+64
-57
lines changed

1 file changed

+64
-57
lines changed

src/sage/sets/primes.py

Lines changed: 64 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ def __classcall__(cls, modulus=1, classes=None, exceptions=None):
225225

226226
# We format the final result and make it hashable
227227
classes = tuple([c for c in range(modulus) if indic[c] is True])
228-
exceptions = [(x, b) for x, b in exceptions.items()
229-
if x.is_prime() and (b != (indic[x % modulus] is True))]
228+
exceptions = [(ZZ(x), b) for x, b in exceptions.items()
229+
if ZZ(x).is_prime() and (b != (indic[x % modulus] is True))]
230230
exceptions.sort()
231231
exceptions = tuple(exceptions)
232232

@@ -547,35 +547,6 @@ def _an_element_(self):
547547
raise ValueError("this set is empty")
548548
return self.next(42)
549549

550-
def in_range(self, start, stop=None):
551-
r"""
552-
Return the list of the elements of this set which are
553-
in the given range.
554-
555-
EXAMPLES::
556-
557-
sage: P = Primes(modulus=3); P
558-
Set of prime numbers congruent to 1 modulo 3: 7, 13, 19, 31, ...
559-
sage: P.in_range(50, 100)
560-
[61, 67, 73, 79, 97]
561-
562-
When a single integer is passed, it is interpreted as the
563-
upper bound::
564-
565-
sage: P.in_range(50)
566-
[7, 13, 19, 31, 37, 43]
567-
"""
568-
if stop is None:
569-
stop = start
570-
start = 1
571-
elements = []
572-
x = start - 1
573-
while True:
574-
x = self.next(x)
575-
if x >= stop:
576-
return elements
577-
elements.append(x)
578-
579550
def unrank(self, n):
580551
r"""
581552
Return the ``n``-th element of this set.
@@ -853,6 +824,11 @@ def intersection(self, other):
853824
sage: P.intersection(Q)
854825
Set of prime numbers congruent to 11 modulo 15: 11, 41, 71, 101, ...
855826
827+
It is also possible to take the intersection with a range::
828+
829+
sage: P.intersection(range(100))
830+
Finite set of prime numbers: 11, 31, 41, 61, 71
831+
856832
TESTS::
857833
858834
sage: P = Primes(modulus=5, exceptions={5: True, 11: False}); P
@@ -869,24 +845,32 @@ def intersection(self, other):
869845
sage: P.intersection(RR)
870846
Traceback (most recent call last):
871847
...
872-
NotImplementedError: boolean operations are only implemented with other sets of prime numbers
848+
NotImplementedError: object does not support iteration
873849
874850
.. SEEALSO::
875851
876852
:meth:`complement_in_primes`, :meth:`union`
877853
"""
878854
if other is ZZ:
879855
return self
880-
if not isinstance(other, Primes):
881-
raise NotImplementedError("boolean operations are only implemented with other sets of prime numbers")
882-
modulus = self._modulus.lcm(other._modulus)
883-
classes = [c for c in range(modulus)
884-
if (c % self._modulus in self._classes
885-
and c % other._modulus in other._classes)]
886-
exceptions = {x: b for x, b in self._exceptions.items()
887-
if not b or x in other}
888-
exceptions.update((x, b) for x, b in other._exceptions.items()
889-
if not b or x in self)
856+
if isinstance(other, Primes):
857+
modulus = self._modulus.lcm(other._modulus)
858+
classes = [c for c in range(modulus)
859+
if (c % self._modulus in self._classes
860+
and c % other._modulus in other._classes)]
861+
exceptions = {x: b for x, b in self._exceptions.items()
862+
if not b or x in other}
863+
exceptions.update((x, b) for x, b in other._exceptions.items()
864+
if not b or x in self)
865+
elif self.is_finite():
866+
modulus = 1
867+
classes = []
868+
exceptions = {x: True for x in self if x in other}
869+
else:
870+
# we try to enumerate the elements of "other"
871+
modulus = 1
872+
classes = []
873+
exceptions = {x: True for x in list(other) if x in self}
890874
return Primes(modulus, classes, exceptions)
891875

892876
def union(self, other):
@@ -922,30 +906,40 @@ def union(self, other):
922906
sage: P.union(RR)
923907
Traceback (most recent call last):
924908
...
925-
NotImplementedError: boolean operations are only implemented with other sets of prime numbers
909+
NotImplementedError: object does not support iteration
926910
927911
.. SEEALSO::
928912
929913
:meth:`complement_in_primes`, :meth:`intersection`
930914
"""
931915
if other is ZZ:
932916
return ZZ
933-
if not isinstance(other, Primes):
934-
raise NotImplementedError("boolean operations are only implemented with other sets of prime numbers")
935-
modulus = self._modulus.lcm(other._modulus)
936-
classes = [c for c in range(modulus)
937-
if (c % self._modulus in self._classes
938-
or c % other._modulus in other._classes)]
939-
exceptions = {x: b for x, b in self._exceptions.items()
940-
if b or x not in other}
941-
exceptions.update((x, b) for x, b in other._exceptions.items()
942-
if b or x not in self)
917+
if isinstance(other, Primes):
918+
modulus = self._modulus.lcm(other._modulus)
919+
classes = [c for c in range(modulus)
920+
if (c % self._modulus in self._classes
921+
or c % other._modulus in other._classes)]
922+
exceptions = {x: b for x, b in self._exceptions.items()
923+
if b or x not in other}
924+
exceptions.update((x, b) for x, b in other._exceptions.items()
925+
if b or x not in self)
926+
else:
927+
# we try to enumerate the elements of "other"
928+
modulus = self._modulus
929+
classes = self._classes
930+
exceptions = self._exceptions.copy()
931+
for x in list(other):
932+
x = ZZ(x)
933+
if x.is_prime():
934+
exceptions[x] = True
935+
else:
936+
raise NotImplementedError("the result of the union is a subset of the set of prime numbers")
943937
return Primes(modulus, classes, exceptions)
944938

945939
def is_almost_equal(self, other):
946940
r"""
947-
Return ``True`` if this set only differs from ``other``
948-
by a finite set; return ``False`` otherwise.
941+
Return whether this set only differs from ``other``
942+
by a finite set.
949943
950944
INPUT:
951945
@@ -973,8 +967,7 @@ def is_almost_equal(self, other):
973967

974968
def is_subset(self, other, almost=False):
975969
r"""
976-
Return ``True`` if this set of is subset of ``other``;
977-
``False`` otherwise.
970+
Return whether this set is a subset of ``other``.
978971
979972
INPUT:
980973
@@ -1004,10 +997,17 @@ def is_subset(self, other, almost=False):
1004997
sage: Q2.is_subset(P, almost=True)
1005998
True
1006999
1000+
TESTS::
1001+
1002+
sage: P.is_subset(ZZ)
1003+
True
1004+
10071005
.. SEEALSO::
10081006
10091007
:meth:`is_superset`, :meth:`is_disjoint`, :meth:`is_almost_equal`
10101008
"""
1009+
if other is ZZ:
1010+
return True
10111011
P = self.intersection(other)
10121012
if almost:
10131013
return P.is_almost_equal(self)
@@ -1046,10 +1046,17 @@ def is_superset(self, other, almost=False):
10461046
sage: P.is_superset(Q2, almost=True)
10471047
True
10481048
1049+
TESTS::
1050+
1051+
sage: P.is_superset(ZZ)
1052+
False
1053+
10491054
.. SEEALSO::
10501055
10511056
:meth:`is_subset`, :meth:`is_disjoint`, :meth:`is_almost_equal`
10521057
"""
1058+
if other is ZZ:
1059+
return False
10531060
P = self.intersection(other)
10541061
if almost:
10551062
return P.is_almost_equal(other)

0 commit comments

Comments
 (0)