Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/sets/integer_range.py
8817 views
1
"""
2
Integer Range
3
4
AUTHORS:
5
6
- Nicolas Borie (2010-03): First release.
7
- Florent Hivert (2010-03): Added a class factory + cardinality method.
8
- Vincent Delecroix (2012-02): add methods rank/unrank, make it complient with
9
Python int.
10
"""
11
#*****************************************************************************
12
# Copyright (C) 2010 Nicolas Borie <[email protected]>
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
# http://www.gnu.org/licenses/
16
#*****************************************************************************
17
18
from sage.structure.parent import Parent
19
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
20
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
21
from sage.structure.unique_representation import UniqueRepresentation
22
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
23
from sage.rings.integer import Integer
24
from sage.rings.integer_ring import IntegerRing
25
from sage.rings.infinity import Infinity, MinusInfinity, PlusInfinity
26
27
class IntegerRange(UniqueRepresentation, Parent):
28
r"""
29
The class of :class:`Integer <sage.rings.integer.Integer>` ranges
30
31
Returns an enumerated set containing an arithmetic progression of integers.
32
33
INPUT:
34
35
- ``begin`` -- an integer, Infinity or -Infinity
36
- ``end`` -- an integer, Infinity or -Infinity
37
- ``step`` -- a non zero integer (default to 1)
38
- ``middle_point`` -- an integer inside the set (default to ``None``)
39
40
OUTPUT:
41
42
A parent in the category :class:`FiniteEnumeratedSets()
43
<sage.categories.finite_enumerated_sets.FiniteEnumeratedSets>` or
44
:class:`InfiniteEnumeratedSets()
45
<sage.categories.infinite_enumerated_sets.InfiniteEnumeratedSets>`
46
depending on the arguments defining ``self``.
47
48
``IntegerRange(i, j)`` returns the set of `\{i, i+1, i+2, \dots , j-1\}`.
49
``start`` (!) defaults to 0. When ``step`` is given, it specifies the
50
increment. The default increment is `1`. IntegerRange allows ``begin`` and
51
``end`` to be infinite.
52
53
``IntegerRange`` is designed to have similar interface Python
54
range. However, whereas ``range`` accept and returns Python ``int``,
55
``IntegerRange`` deals with :class:`Integer <sage.rings.integer.Integer>`.
56
57
If ``middle_point`` is given, then the elements are generated starting
58
from it, in a alternating way: `\{m, m+1, m-2, m+2, m-2 \dots \}`.
59
60
EXAMPLES::
61
62
sage: list(IntegerRange(5))
63
[0, 1, 2, 3, 4]
64
sage: list(IntegerRange(2,5))
65
[2, 3, 4]
66
sage: I = IntegerRange(2,100,5); I
67
{2, 7, .., 97}
68
sage: list(I)
69
[2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97]
70
sage: I.category()
71
Category of facade finite enumerated sets
72
sage: I[1].parent()
73
Integer Ring
74
75
When ``begin`` and ``end`` are both finite, ``IntegerRange(begin, end,
76
step)`` is the set whose list of elements is equivalent to the python
77
construction ``range(begin, end, step)``::
78
79
sage: list(IntegerRange(4,105,3)) == range(4,105,3)
80
True
81
sage: list(IntegerRange(-54,13,12)) == range(-54,13,12)
82
True
83
84
Except for the type of the numbers::
85
86
sage: type(IntegerRange(-54,13,12)[0]), type(range(-54,13,12)[0])
87
(<type 'sage.rings.integer.Integer'>, <type 'int'>)
88
89
When ``begin`` is finite and ``end`` is +Infinity, ``self`` is the infinite
90
arithmetic progression starting from the ``begin`` by step ``step``::
91
92
sage: I = IntegerRange(54,Infinity,3); I
93
{54, 57, ..}
94
sage: I.category()
95
Category of facade infinite enumerated sets
96
sage: p = iter(I)
97
sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next())
98
(54, 57, 60, 63, 66, 69)
99
100
sage: I = IntegerRange(54,-Infinity,-3); I
101
{54, 51, ..}
102
sage: I.category()
103
Category of facade infinite enumerated sets
104
sage: p = iter(I)
105
sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next())
106
(54, 51, 48, 45, 42, 39)
107
108
When ``begin`` and ``end`` are both infinite, you will have to specify the
109
extra argument ``middle_point``. ``self`` is then defined by a point
110
and a progression/regression setting by ``step``. The enumeration
111
is done this way: (let us call `m` the ``middle_point``)
112
`\{m, m+step, m-step, m+2step, m-2step, m+3step, \dots \}`::
113
114
sage: I = IntegerRange(-Infinity,Infinity,37,-12); I
115
Integer progression containing -12 with increment 37 and bounded with -Infinity and +Infinity
116
sage: I.category()
117
Category of facade infinite enumerated sets
118
sage: -12 in I
119
True
120
sage: -15 in I
121
False
122
sage: p = iter(I)
123
sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next())
124
(-12, 25, -49, 62, -86, 99, -123, 136)
125
126
It is also possible to use the argument ``middle_point`` for other cases, finite
127
or infinite. The set will be the same as if you didn't give this extra argument
128
but the enumeration will begin with this ``middle_point``::
129
130
sage: I = IntegerRange(123,-12,-14); I
131
{123, 109, .., -3}
132
sage: list(I)
133
[123, 109, 95, 81, 67, 53, 39, 25, 11, -3]
134
sage: J = IntegerRange(123,-12,-14,25); J
135
Integer progression containing 25 with increment -14 and bounded with 123 and -12
136
sage: list(J)
137
[25, 11, 39, -3, 53, 67, 81, 95, 109, 123]
138
139
Remember that, like for range, if you define a non empty set, ``begin`` is
140
supposed to be included and ``end`` is supposed to be excluded. In the same
141
way, when you define a set with a ``middle_point``, the ``begin`` bound will
142
be supposed to be included and the ``end`` bound supposed to be excluded::
143
144
sage: I = IntegerRange(-100,100,10,0)
145
sage: J = range(-100,100,10)
146
sage: 100 in I
147
False
148
sage: 100 in J
149
False
150
sage: -100 in I
151
True
152
sage: -100 in J
153
True
154
sage: list(I)
155
[0, 10, -10, 20, -20, 30, -30, 40, -40, 50, -50, 60, -60, 70, -70, 80, -80, 90, -90, -100]
156
157
158
.. note::
159
160
The input is normalized so that::
161
162
sage: IntegerRange(1, 6, 2) is IntegerRange(1, 7, 2)
163
True
164
sage: IntegerRange(1, 8, 3) is IntegerRange(1, 10, 3)
165
True
166
167
TESTS::
168
169
sage: # Some category automatic tests
170
sage: TestSuite(IntegerRange(2,100,3)).run()
171
sage: TestSuite(IntegerRange(564,-12,-46)).run()
172
sage: TestSuite(IntegerRange(2,Infinity,3)).run()
173
sage: TestSuite(IntegerRange(732,-Infinity,-13)).run()
174
sage: TestSuite(IntegerRange(-Infinity,Infinity,3,2)).run()
175
sage: TestSuite(IntegerRange(56,Infinity,12,80)).run()
176
sage: TestSuite(IntegerRange(732,-12,-2743,732)).run()
177
sage: # 20 random tests: range and IntegerRange give the same set for finite cases
178
sage: for i in range(20):
179
... begin = Integer(randint(-300,300))
180
... end = Integer(randint(-300,300))
181
... step = Integer(randint(-20,20))
182
... if step == 0:
183
... step = Integer(1)
184
... assert list(IntegerRange(begin, end, step)) == range(begin, end, step)
185
sage: # 20 random tests: range and IntegerRange with middle point for finite cases
186
sage: for i in range(20):
187
... begin = Integer(randint(-300,300))
188
... end = Integer(randint(-300,300))
189
... step = Integer(randint(-15,15))
190
... if step == 0:
191
... step = Integer(-3)
192
... I = IntegerRange(begin, end, step)
193
... if I.cardinality() == 0:
194
... assert len(range(begin, end, step)) == 0
195
... else:
196
... TestSuite(I).run()
197
... L1 = list(IntegerRange(begin, end, step, I.an_element()))
198
... L2 = range(begin, end, step)
199
... L1.sort()
200
... L2.sort()
201
... assert L1 == L2
202
203
Thanks to #8543 empty integer range are allowed::
204
205
sage: TestSuite(IntegerRange(0, 5, -1)).run()
206
"""
207
208
@staticmethod
209
def __classcall_private__(cls, begin, end=None, step=Integer(1), middle_point=None):
210
"""
211
TESTS::
212
213
sage: IntegerRange(2,5,0)
214
Traceback (most recent call last):
215
...
216
ValueError: IntegerRange() step argument must not be zero
217
sage: IntegerRange(2) is IntegerRange(0, 2)
218
True
219
"""
220
if isinstance(begin, int): begin = Integer(begin)
221
if isinstance(end, int): end = Integer(end)
222
if isinstance(step,int): step = Integer(step)
223
224
if end is None:
225
end = begin
226
begin = Integer(0)
227
# check of the arguments
228
assert isinstance(begin, (Integer, MinusInfinity, PlusInfinity))
229
assert isinstance(end, (Integer, MinusInfinity, PlusInfinity))
230
assert isinstance(step, Integer)
231
if step.is_zero():
232
raise ValueError("IntegerRange() step argument must not be zero")
233
234
# If begin and end are infinite, middle_point and step will defined the set.
235
if begin == -Infinity and end == Infinity:
236
if middle_point == None:
237
raise ValueError("Can't iterate over this set, please provide middle_point")
238
239
# If we have a middle point, we go on the special enumeration way...
240
if middle_point != None:
241
return IntegerRangeFromMiddle(begin, end, step, middle_point)
242
243
if (begin == -Infinity) or (begin == Infinity):
244
raise ValueError("Can't iterate over this set: It is impossible to begin an enumeration with plus/minus Infinity")
245
246
# Check for empty sets
247
if step > 0 and begin >= end or step < 0 and begin <= end:
248
return IntegerRangeEmpty()
249
250
if end != Infinity and end != -Infinity:
251
# Normalize the input
252
sgn = 1 if step > 0 else -1
253
end = begin+((end-begin-sgn)//(step)+1)*step
254
return IntegerRangeFinite(begin, end, step)
255
else:
256
return IntegerRangeInfinite(begin, step)
257
258
def _element_constructor_(self, el):
259
"""
260
TESTS::
261
262
sage: S = IntegerRange(1, 10, 2)
263
sage: S(1) #indirect doctest
264
1
265
sage: S(0) #indirect doctest
266
Traceback (most recent call last):
267
...
268
ValueError: 0 not in {1, 3, 5, 7, 9}
269
"""
270
if el in self:
271
if not isinstance(el,Integer):
272
return Integer(el)
273
return el
274
else:
275
raise ValueError, "%s not in %s"%(el, self)
276
277
element_class = Integer
278
279
class IntegerRangeEmpty(IntegerRange, FiniteEnumeratedSet):
280
r"""
281
A singleton class for empty integer ranges
282
283
See :class:`IntegerRange` for more details.
284
"""
285
286
# Needed because FiniteEnumeratedSet.__classcall__ takes an argument.
287
@staticmethod
288
def __classcall__(cls, *args):
289
"""
290
TESTS::
291
292
sage: from sage.sets.integer_range import IntegerRangeEmpty
293
sage: I = IntegerRangeEmpty(); I
294
{}
295
sage: I.category()
296
Category of facade finite enumerated sets
297
sage: TestSuite(I).run()
298
sage: I(0)
299
Traceback (most recent call last):
300
...
301
ValueError: 0 not in {}
302
"""
303
return FiniteEnumeratedSet.__classcall__(cls, ())
304
305
class IntegerRangeFinite(IntegerRange):
306
r"""
307
The class of finite enumerated sets of integers defined by finite
308
arithmetic progressions
309
310
See :class:`IntegerRange` for more details.
311
"""
312
def __init__(self, begin, end, step=Integer(1)):
313
r"""
314
TESTS::
315
316
sage: I = IntegerRange(123,12,-4)
317
sage: I.category()
318
Category of facade finite enumerated sets
319
sage: TestSuite(I).run()
320
"""
321
self._begin = begin
322
self._end = end
323
self._step = step
324
Parent.__init__(self, facade = IntegerRing(), category = FiniteEnumeratedSets())
325
326
def __contains__(self, elt):
327
r"""
328
Returns True if ``elt`` is in ``self``.
329
330
EXAMPLES::
331
332
sage: I = IntegerRange(123,12,-4)
333
sage: 123 in I
334
True
335
sage: 127 in I
336
False
337
sage: 12 in I
338
False
339
sage: 13 in I
340
False
341
sage: 14 in I
342
False
343
sage: 15 in I
344
True
345
sage: 11 in I
346
False
347
"""
348
if not isinstance(elt, Integer):
349
try:
350
x = Integer(elt)
351
if x != elt:
352
return False
353
elt = x
354
except (ValueError, TypeError):
355
return False
356
if (self._step.__abs__()).divides(Integer(elt)-self._begin):
357
return (self._begin <= elt < self._end and self._step > 0) or \
358
(self._begin >= elt > self._end and self._step < 0)
359
return False
360
361
def cardinality(self):
362
"""
363
Return the cardinality of ``self``
364
365
EXAMPLES::
366
367
sage: IntegerRange(123,12,-4).cardinality()
368
28
369
sage: IntegerRange(-57,12,8).cardinality()
370
9
371
sage: IntegerRange(123,12,4).cardinality()
372
0
373
"""
374
return (abs((self._end+self._step-self._begin))-1) // abs(self._step)
375
376
def _repr_(self):
377
"""
378
EXAMPLES::
379
380
sage: IntegerRange(1,2) #indirect doctest
381
{1}
382
sage: IntegerRange(1,3) #indirect doctest
383
{1, 2}
384
sage: IntegerRange(1,5) #indirect doctest
385
{1, 2, 3, 4}
386
sage: IntegerRange(1,6) #indirect doctest
387
{1, ..., 5}
388
sage: IntegerRange(123,12,-4) #indirect doctest
389
{123, 119, ..., 15}
390
sage: IntegerRange(-57,1,3) #indirect doctest
391
{-57, -54, ..., 0}
392
"""
393
if self.cardinality() < 6:
394
return "{" + ", ".join(str(x) for x in self) + "}"
395
elif self._step == 1:
396
return "{%s, .., %s}"%(self._begin, self._end-self._step)
397
else:
398
return "{%s, %s, .., %s}"%(self._begin, self._begin+self._step,
399
self._end-self._step)
400
401
def rank(self,x):
402
r"""
403
EXAMPLES::
404
405
sage: I = IntegerRange(-57,36,8)
406
sage: I.rank(23)
407
10
408
sage: I.unrank(10)
409
23
410
sage: I.rank(22)
411
Traceback (most recent call last):
412
...
413
IndexError: 22 not in self
414
sage: I.rank(87)
415
Traceback (most recent call last):
416
...
417
IndexError: 87 not in self
418
"""
419
if x not in self:
420
raise IndexError, "%s not in self"%x
421
return Integer((x - self._begin)/self._step)
422
423
def __getitem__(self, i):
424
r"""
425
Return the i-th elt of this integer range.
426
427
EXAMPLES::
428
429
sage: I=IntegerRange(1,13,5)
430
sage: I[0], I[1], I[2]
431
(1, 6, 11)
432
sage: I[3]
433
Traceback (most recent call last):
434
...
435
IndexError: out of range
436
sage: I[-1]
437
11
438
sage: I[-4]
439
Traceback (most recent call last):
440
...
441
IndexError: out of range
442
443
sage: I = IntegerRange(13,1,-1)
444
sage: l = I.list()
445
sage: [I[i] for i in xrange(I.cardinality())] == l
446
True
447
sage: l.reverse()
448
sage: [I[i] for i in xrange(-1,-I.cardinality()-1,-1)] == l
449
True
450
"""
451
if isinstance(i,slice):
452
raise NotImplementedError("not yet")
453
454
if isinstance(i, int):
455
i = Integer(i)
456
elif not isinstance(i,Integer):
457
raise ValueError("argument should be an integer")
458
459
if i < 0:
460
if i < -self.cardinality():
461
raise IndexError("out of range")
462
n = (self._end - self._begin)//(self._step)
463
return self._begin + (n+i)*self._step
464
else:
465
if i >= self.cardinality():
466
raise IndexError("out of range")
467
return self._begin + i * self._step
468
469
unrank = __getitem__
470
471
def __iter__(self):
472
r"""
473
Returns an iterator over the elements of ``self``
474
475
EXAMPLES::
476
477
sage: I = IntegerRange(123,12,-4)
478
sage: p = iter(I)
479
sage: [p.next() for i in range(8)]
480
[123, 119, 115, 111, 107, 103, 99, 95]
481
sage: I = IntegerRange(-57,12,8)
482
sage: p = iter(I)
483
sage: [p.next() for i in range(8)]
484
[-57, -49, -41, -33, -25, -17, -9, -1]
485
"""
486
n = self._begin
487
if self._step > 0:
488
while n < self._end:
489
yield n
490
n += self._step
491
else:
492
while n > self._end:
493
yield n
494
n += self._step
495
496
def _an_element_(self):
497
r"""
498
Returns an element of ``self``.
499
500
EXAMPLES::
501
502
sage: I = IntegerRange(123,12,-4)
503
sage: I.an_element() #indirect doctest
504
115
505
sage: I = IntegerRange(-57,12,8)
506
sage: I.an_element() #indirect doctest
507
-41
508
"""
509
p = (self._begin + 2*self._step)
510
if p in self:
511
return p
512
else:
513
return self._begin
514
515
class IntegerRangeInfinite(IntegerRange):
516
r""" The class of infinite enumerated sets of integers defined by infinite
517
arithmetic progressions.
518
519
See :class:`IntegerRange` for more details.
520
"""
521
def __init__(self, begin, step=Integer(1)):
522
r"""
523
TESTS::
524
525
sage: I = IntegerRange(-57,Infinity,8)
526
sage: I.category()
527
Category of facade infinite enumerated sets
528
sage: TestSuite(I).run()
529
"""
530
assert isinstance(begin, Integer)
531
self._begin = begin
532
self._step = step
533
Parent.__init__(self, facade = IntegerRing(), category = InfiniteEnumeratedSets())
534
535
def _repr_(self):
536
r"""
537
TESTS::
538
539
sage: IntegerRange(123,12,-4) #indirect doctest
540
{123, 119, .., 15}
541
sage: IntegerRange(-57,1,3) #indirect doctest
542
{-57, -54, .., 0}
543
544
sage: IntegerRange(-57,Infinity,8) #indirect doctest
545
{-57, -49, ..}
546
sage: IntegerRange(-112,-Infinity,-13) #indirect doctest
547
{-112, -125, ..}
548
"""
549
return "{%s, %s, ..}"%(self._begin, self._begin+self._step)
550
551
def __contains__(self, elt):
552
r"""
553
Returns True if ``elt`` is in ``self``.
554
555
EXAMPLES::
556
557
sage: I = IntegerRange(-57,Infinity,8)
558
sage: -57 in I
559
True
560
sage: -65 in I
561
False
562
sage: -49 in I
563
True
564
sage: 743 in I
565
True
566
"""
567
if not isinstance(elt, Integer):
568
try:
569
elt = Integer(elt)
570
except (TypeError, ValueError):
571
return False
572
if (self._step.__abs__()).divides(Integer(elt)-self._begin):
573
return (self._step > 0 and elt >= self._begin) or \
574
(self._step < 0 and elt <= self._begin)
575
return False
576
577
def rank(self, x):
578
r"""
579
EXAMPLES::
580
581
sage: I = IntegerRange(-57,Infinity,8)
582
sage: I.rank(23)
583
10
584
sage: I.unrank(10)
585
23
586
sage: I.rank(22)
587
Traceback (most recent call last):
588
...
589
IndexError: 22 not in self
590
"""
591
if x not in self:
592
raise IndexError, "%s not in self"%x
593
return Integer((x - self._begin)/self._step)
594
595
def __getitem__(self, i):
596
r"""
597
Returns the ``i``-th element of self.
598
599
EXAMPLES::
600
601
sage: I = IntegerRange(-8,Infinity,3)
602
sage: I.unrank(1)
603
-5
604
"""
605
if isinstance(i,slice):
606
raise NotImplementedError, "not yet"
607
608
if isinstance(i, int):
609
i = Integer(i)
610
elif not isinstance(i,Integer):
611
raise ValueError
612
613
if i < 0:
614
raise IndexError, "out of range"
615
else:
616
return self._begin + i * self._step
617
618
unrank = __getitem__
619
620
def __iter__(self):
621
r"""
622
Returns an iterator over the elements of ``self``.
623
624
EXAMPLES::
625
626
sage: I = IntegerRange(-57,Infinity,8)
627
sage: p = iter(I)
628
sage: [p.next() for i in range(8)]
629
[-57, -49, -41, -33, -25, -17, -9, -1]
630
631
sage: I = IntegerRange(-112,-Infinity,-13)
632
sage: p = iter(I)
633
sage: [p.next() for i in range(8)]
634
[-112, -125, -138, -151, -164, -177, -190, -203]
635
"""
636
n = self._begin
637
while True:
638
yield n
639
n += self._step
640
641
def _an_element_(self):
642
r"""
643
Returns an element of ``self``.
644
645
EXAMPLES::
646
647
sage: I = IntegerRange(-57,Infinity,8)
648
sage: I.an_element() #indirect doctest
649
191
650
651
sage: I = IntegerRange(-112,-Infinity,-13)
652
sage: I.an_element() #indirect doctest
653
-515
654
"""
655
return self._begin + 31*self._step
656
657
class IntegerRangeFromMiddle(IntegerRange):
658
r"""
659
The class of finite or infinite enumerated sets defined with
660
an inside point, a progression and two limits.
661
662
See :class:`IntegerRange` for more details.
663
"""
664
def __init__(self, begin, end, step=Integer(1), middle_point=Integer(1)):
665
r"""
666
TESTS::
667
668
sage: from sage.sets.integer_range import IntegerRangeFromMiddle
669
sage: I = IntegerRangeFromMiddle(-100,100,10,0)
670
sage: I.category()
671
Category of facade finite enumerated sets
672
sage: TestSuite(I).run()
673
sage: I = IntegerRangeFromMiddle(Infinity,-Infinity,-37,0)
674
sage: I.category()
675
Category of facade infinite enumerated sets
676
sage: TestSuite(I).run()
677
678
sage: IntegerRange(0, 5, 1, -3)
679
Traceback (most recent call last):
680
...
681
AssertionError: middle_point is not in the interval
682
"""
683
self._begin = begin
684
self._end = end
685
self._step = step
686
self._middle_point = middle_point
687
assert middle_point in self, "middle_point is not in the interval"
688
689
if (begin != Infinity and begin != -Infinity) and \
690
(end != Infinity and end != -Infinity):
691
Parent.__init__(self, facade = IntegerRing(), category = FiniteEnumeratedSets())
692
else:
693
Parent.__init__(self, facade = IntegerRing(), category = InfiniteEnumeratedSets())
694
695
def _repr_(self):
696
r"""
697
TESTS::
698
699
sage: from sage.sets.integer_range import IntegerRangeFromMiddle
700
sage: IntegerRangeFromMiddle(Infinity,-Infinity,-37,0) #indirect doctest
701
Integer progression containing 0 with increment -37 and bounded with +Infinity and -Infinity
702
sage: IntegerRangeFromMiddle(-100,100,10,0) #indirect doctest
703
Integer progression containing 0 with increment 10 and bounded with -100 and 100
704
"""
705
return "Integer progression containing %s with increment %s and bounded with %s and %s"%(self._middle_point,self._step,self._begin,self._end)
706
707
def __contains__(self, elt):
708
r"""
709
Returns True if ``elt`` is in ``self``.
710
711
EXAMPLES::
712
713
sage: from sage.sets.integer_range import IntegerRangeFromMiddle
714
sage: I = IntegerRangeFromMiddle(-100,100,10,0)
715
sage: -110 in I
716
False
717
sage: -100 in I
718
True
719
sage: 30 in I
720
True
721
sage: 90 in I
722
True
723
sage: 100 in I
724
False
725
"""
726
if not isinstance(elt, Integer):
727
try:
728
elt = Integer(elt)
729
except (TypeError, ValueError):
730
return False
731
if (self._step.__abs__()).divides(Integer(elt)-self._middle_point):
732
return (self._begin <= elt and elt < self._end) or \
733
(self._begin >= elt and elt > self._end)
734
return False
735
736
def next(self, elt):
737
r"""
738
Return the next element of ``elt`` in ``self``.
739
740
EXAMPLES::
741
742
sage: from sage.sets.integer_range import IntegerRangeFromMiddle
743
sage: I = IntegerRangeFromMiddle(-100,100,10,0)
744
sage: (I.next(0), I.next(10), I.next(-10), I.next(20), I.next(-100))
745
(10, -10, 20, -20, None)
746
sage: I = IntegerRangeFromMiddle(-Infinity,Infinity,10,0)
747
sage: (I.next(0), I.next(10), I.next(-10), I.next(20), I.next(-100))
748
(10, -10, 20, -20, 110)
749
"""
750
assert (elt in self)
751
n = self._middle_point
752
if (elt <= n and self._step > 0) or (elt >= n and self._step < 0):
753
right = 2*n-elt+self._step
754
if right in self:
755
return right
756
else:
757
left = elt-self._step
758
if left in self:
759
return left
760
else:
761
left = 2*n-elt
762
if left in self:
763
return left
764
else:
765
right = elt+self._step
766
if right in self:
767
return right
768
769
def __iter__(self):
770
r"""
771
Returns an iterator over the elements of ``self``.
772
773
EXAMPLES::
774
775
sage: from sage.sets.integer_range import IntegerRangeFromMiddle
776
sage: I = IntegerRangeFromMiddle(Infinity,-Infinity,-37,0)
777
sage: p = iter(I)
778
sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next())
779
(0, -37, 37, -74, 74, -111, 111, -148)
780
sage: I = IntegerRangeFromMiddle(-12,214,10,0)
781
sage: p = iter(I)
782
sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next())
783
(0, 10, -10, 20, 30, 40, 50, 60)
784
"""
785
n = self._middle_point
786
while n != None:
787
yield n
788
n = self.next(n)
789
790
def _an_element_(self):
791
r"""
792
Returns an element of ``self``.
793
794
EXAMPLES::
795
796
sage: from sage.sets.integer_range import IntegerRangeFromMiddle
797
sage: I = IntegerRangeFromMiddle(Infinity,-Infinity,-37,0)
798
sage: I.an_element() #indirect doctest
799
0
800
sage: I = IntegerRangeFromMiddle(-12,214,10,0)
801
sage: I.an_element() #indirect doctest
802
0
803
"""
804
return self._middle_point
805
806