Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/infinity.py
4048 views
1
r"""
2
Infinity Rings
3
4
The unsigned infinity "ring" is the set of two elements
5
6
1. infinity
7
8
2. A number less than infinity
9
10
The rules for arithmetic are that the unsigned infinity ring does
11
not canonically coerce to any other ring, and all other rings
12
canonically coerce to the unsigned infinity ring, sending all
13
elements to the single element "a number less than infinity" of the
14
unsigned infinity ring. Arithmetic and comparisons then take place
15
in the unsigned infinity ring, where all arithmetic operations that
16
are well-defined are defined.
17
18
The infinity "ring" is the set of five elements
19
20
1. plus infinity
21
22
2. a positive finite element
23
24
3. zero
25
26
4. a negative finite element
27
28
5. negative infinity
29
30
The infinity ring coerces to the unsigned infinity ring, sending
31
the infinite elements to infinity and the non-infinite elements to
32
"a number less than infinity." Any ordered ring coerces to the
33
infinity ring in the obvious way.
34
35
Note: the shorthand oo is predefined in Sage to be the same as
36
+Infinity in the infinity ring. It is considered equal to, but not
37
the same as Infinity in the UnsignedInfinityRing::
38
39
sage: oo
40
+Infinity
41
sage: oo is InfinityRing.0
42
True
43
sage: oo is UnsignedInfinityRing.0
44
False
45
sage: oo == UnsignedInfinityRing.0
46
True
47
48
EXAMPLES:
49
50
We fetch the unsigned infinity ring and create some
51
elements::
52
53
sage: P = UnsignedInfinityRing; P
54
The Unsigned Infinity Ring
55
sage: P(5)
56
A number less than infinity
57
sage: P.ngens()
58
1
59
sage: unsigned_oo = P.0; unsigned_oo
60
Infinity
61
62
We compare finite numbers with infinity::
63
64
sage: 5 < unsigned_oo
65
True
66
sage: 5 > unsigned_oo
67
False
68
sage: unsigned_oo < 5
69
False
70
sage: unsigned_oo > 5
71
True
72
73
We do arithmetic::
74
75
sage: unsigned_oo + 5
76
Infinity
77
78
We make 1 / unsigned_oo return the integer 0 so that arithmetic of
79
the following type works::
80
81
sage: (1/unsigned_oo) + 2
82
2
83
sage: 32/5 - (2.439/unsigned_oo)
84
32/5
85
86
Note that many operations are not defined, since the result is not
87
well-defined::
88
89
sage: unsigned_oo/0
90
Traceback (most recent call last):
91
...
92
ValueError: unsigned oo times smaller number not defined
93
94
What happened above is that 0 is canonically coerced to "a number
95
less than infinity" in the unsigned infinity ring, and the quotient
96
is then not well-defined.
97
98
::
99
100
sage: 0/unsigned_oo
101
0
102
sage: unsigned_oo * 0
103
Traceback (most recent call last):
104
...
105
ValueError: unsigned oo times smaller number not defined
106
sage: unsigned_oo/unsigned_oo
107
Traceback (most recent call last):
108
...
109
ValueError: unsigned oo times smaller number not defined
110
111
In the infinity ring, we can negate infinity, multiply positive
112
numbers by infinity, etc.
113
114
::
115
116
sage: P = InfinityRing; P
117
The Infinity Ring
118
sage: P(5)
119
A positive finite number
120
121
The symbol oo is predefined as a shorthand for +Infinity::
122
123
sage: oo
124
+Infinity
125
126
We compare finite and infinite elements::
127
128
sage: 5 < oo
129
True
130
sage: P(-5) < P(5)
131
True
132
sage: P(2) < P(3)
133
False
134
sage: -oo < oo
135
True
136
137
We can do more arithmetic than in the unsigned infinity ring::
138
139
sage: 2 * oo
140
+Infinity
141
sage: -2 * oo
142
-Infinity
143
sage: 1 - oo
144
-Infinity
145
sage: 1 / oo
146
0
147
sage: -1 / oo
148
0
149
150
We make 1 / oo and 1 / -oo return the integer 0 instead of the
151
infinity ring Zero so that arithmetic of the following type works::
152
153
sage: (1/oo) + 2
154
2
155
sage: 32/5 - (2.439/-oo)
156
32/5
157
158
If we try to subtract infinities or multiply infinity by zero we
159
still get an error::
160
161
sage: oo - oo
162
Traceback (most recent call last):
163
...
164
SignError: cannot add infinity to minus infinity
165
sage: 0 * oo
166
Traceback (most recent call last):
167
...
168
SignError: cannot multiply infinity by zero
169
sage: P(2) + P(-3)
170
Traceback (most recent call last):
171
...
172
SignError: cannot add positive finite value to negative finite value
173
174
TESTS::
175
176
sage: P = InfinityRing
177
sage: P == loads(dumps(P))
178
True
179
180
::
181
182
sage: P(2) == loads(dumps(P(2)))
183
True
184
185
The following is assumed in a lot of code (i.e., "is" is used for
186
testing whether something is infinity), so make sure it is
187
satisfied::
188
189
sage: loads(dumps(infinity)) is infinity
190
True
191
"""
192
193
from sage.rings.ring_element import RingElement
194
from sage.rings.ring import Ring
195
from sage.structure.element import RingElement, InfinityElement, PlusInfinityElement, MinusInfinityElement
196
from sage.structure.parent_gens import ParentWithGens
197
#import sage.rings.real_double
198
#import sage.rings.real_mpfr
199
import sage.rings.integer
200
import sage.rings.rational
201
202
from sage.rings.integer_ring import ZZ
203
204
_obj = {}
205
class _uniq(object):
206
def __new__(cls, *args):
207
"""
208
This ensures uniqueness of these objects.
209
210
EXAMPLE::
211
212
sage: sage.rings.infinity.UnsignedInfinityRing_class() is sage.rings.infinity.UnsignedInfinityRing_class()
213
True
214
"""
215
if _obj.has_key(cls):
216
return _obj[cls]
217
_obj[cls] = O = cls.__bases__[-1].__new__(cls, *args)
218
return O
219
220
class AnInfinity:
221
222
def _repr_(self):
223
"""
224
TESTS::
225
226
sage: [x._repr_() for x in [unsigned_infinity, oo, -oo]]
227
['Infinity', '+Infinity', '-Infinity']
228
"""
229
return self._sign_char + "Infinity"
230
231
def _giac_init_(self):
232
"""
233
TESTS::
234
235
sage: [x._repr_() for x in [unsigned_infinity, oo, -oo]]
236
['Infinity', '+Infinity', '-Infinity']
237
"""
238
return self._sign_char + "infinity"
239
240
def _maxima_init_(self):
241
"""
242
TESTS::
243
244
sage: maxima(-oo)
245
minf
246
sage: [x._maxima_init_() for x in [unsigned_infinity, oo, -oo]]
247
['inf', 'inf', 'minf']
248
"""
249
if self._sign < 0:
250
return 'minf'
251
else:
252
return 'inf'
253
254
def _pari_(self):
255
"""
256
Convert self to a Pari object.
257
258
This always raises an exception since Pari does not have
259
infinities.
260
261
TESTS::
262
263
sage: pari(-oo)
264
Traceback (most recent call last):
265
...
266
TypeError: cannot convert infinity to Pari
267
sage: pari(oo)
268
Traceback (most recent call last):
269
...
270
TypeError: cannot convert infinity to Pari
271
"""
272
raise TypeError, 'cannot convert infinity to Pari'
273
274
def _latex_(self):
275
"""
276
EXAMPLES::
277
278
sage: latex(oo)
279
+\infty
280
sage: [x._latex_() for x in [unsigned_infinity, oo, -oo]]
281
['\\infty', '+\\infty', '-\\infty']
282
"""
283
return self._sign_char + "\\infty"
284
285
def __cmp__(self, other):
286
"""
287
EXAMPLES::
288
289
sage: oo == oo
290
True
291
sage: oo < oo
292
False
293
sage: -oo < oo
294
True
295
sage: -oo < 3 < oo
296
True
297
298
sage: unsigned_infinity == 3
299
False
300
sage: unsigned_infinity == unsigned_infinity
301
True
302
sage: unsigned_infinity == oo
303
True
304
"""
305
if isinstance(other, AnInfinity):
306
return cmp(self._sign, other._sign)
307
elif self._sign:
308
return self._sign
309
else:
310
return 1
311
312
def __abs__(self):
313
"""
314
EXAMPLES::
315
316
sage: [abs(x) for x in [UnsignedInfinityRing.gen(), oo, -oo]]
317
[Infinity, +Infinity, +Infinity]
318
"""
319
return -self if self._sign < 0 else self
320
321
def _add_(self, other):
322
"""
323
EXAMPLES::
324
325
sage: -oo + -oo
326
-Infinity
327
sage: -oo + 3
328
-Infinity
329
sage: oo + -100
330
+Infinity
331
sage: oo + -oo
332
Traceback (most recent call last):
333
...
334
SignError: cannot add infinity to minus infinity
335
336
sage: unsigned_infinity = UnsignedInfinityRing.gen()
337
sage: unsigned_infinity + unsigned_infinity
338
Infinity
339
sage: unsigned_infinity + 88/3
340
Infinity
341
"""
342
if isinstance(other, AnInfinity):
343
if self._sign != other._sign:
344
raise SignError, "cannot add infinity to minus infinity"
345
return self
346
347
def _sub_(self, other):
348
"""
349
EXAMPLES::
350
351
sage: -oo - oo
352
-Infinity
353
sage: oo - -oo
354
+Infinity
355
sage: oo - 4
356
+Infinity
357
sage: -oo - 1
358
-Infinity
359
sage: oo - oo
360
Traceback (most recent call last):
361
...
362
SignError: cannot add infinity to minus infinity
363
sage: unsigned_infinity - 4
364
Infinity
365
sage: unsigned_infinity - unsigned_infinity
366
Traceback (most recent call last):
367
...
368
ValueError: oo - oo not defined
369
"""
370
if isinstance(other, AnInfinity):
371
if self._sign == 0:
372
raise ValueError, "oo - oo not defined"
373
elif self._sign == other._sign:
374
raise SignError, "cannot add infinity to minus infinity"
375
return self
376
377
def _mul_(self, other):
378
"""
379
EXAMPLES::
380
381
sage: oo * 19
382
+Infinity
383
sage: oo * oo
384
+Infinity
385
sage: -oo * oo
386
-Infinity
387
sage: -oo * 4
388
-Infinity
389
sage: -oo * -2/3
390
+Infinity
391
sage: -oo * 0
392
Traceback (most recent call last):
393
...
394
SignError: cannot multiply infinity by zero
395
"""
396
if other < 0:
397
return -self
398
if other > 0:
399
return self
400
raise SignError, "cannot multiply infinity by zero"
401
402
def _div_(self, other):
403
"""
404
EXAMPLES::
405
406
sage: 1.5 / oo
407
0
408
sage: oo / -4
409
-Infinity
410
sage: oo / oo
411
Traceback (most recent call last):
412
...
413
SignError: cannot multiply infinity by zero
414
"""
415
return self * ~other
416
417
def __float__(self):
418
r"""
419
Generate a floating-point infinity. The printing of
420
floating-point infinity varies across platforms.
421
422
EXAMPLES::
423
424
sage: RDF(infinity)
425
+infinity
426
sage: float(infinity) # random
427
+infinity
428
sage: CDF(infinity)
429
+infinity
430
sage: infinity.__float__() # random
431
+infinity
432
433
sage: RDF(-infinity)
434
-infinity
435
sage: float(-infinity) # random
436
-inf
437
sage: CDF(-infinity)
438
-infinity
439
sage: (-infinity).__float__() # random
440
-inf
441
442
"""
443
# Evidently there is no standard way to generate an infinity
444
# in Python (before Python 2.6).
445
from sage.rings.all import RR
446
return float(RR(self))
447
448
def lcm(self, x):
449
"""
450
Return the least common multiple of oo and x, which
451
is by definition oo unless x is 0.
452
453
EXAMPLES::
454
455
sage: oo.lcm(0)
456
0
457
sage: oo.lcm(oo)
458
+Infinity
459
sage: oo.lcm(-oo)
460
+Infinity
461
sage: oo.lcm(10)
462
+Infinity
463
sage: (-oo).lcm(10)
464
+Infinity
465
"""
466
if x == 0:
467
return x
468
else:
469
return abs(self)
470
471
472
class UnsignedInfinityRing_class(_uniq, Ring):
473
474
def __init__(self):
475
"""
476
TESTS::
477
478
sage: sage.rings.infinity.UnsignedInfinityRing_class() is sage.rings.infinity.UnsignedInfinityRing_class() is UnsignedInfinityRing
479
True
480
"""
481
ParentWithGens.__init__(self, self, names=('oo',), normalize=False)
482
483
def ngens(self):
484
"""
485
The unsigned infinity ring has one "generator."
486
487
EXAMPLES::
488
489
sage: UnsignedInfinityRing.ngens()
490
1
491
sage: len(UnsignedInfinityRing.gens())
492
1
493
"""
494
return 1
495
496
def fraction_field(self):
497
"""
498
The unsigned infinity ring isn't an integral domain.
499
500
EXAMPLES::
501
502
sage: UnsignedInfinityRing.fraction_field()
503
Traceback (most recent call last):
504
...
505
TypeError: infinity 'ring' has no fraction field
506
"""
507
raise TypeError, "infinity 'ring' has no fraction field"
508
509
def gen(self, n=0):
510
"""
511
The "generator" of self is the infinity object.
512
513
EXAMPLES::
514
515
sage: UnsignedInfinityRing.gen()
516
Infinity
517
sage: UnsignedInfinityRing.gen(1)
518
Traceback (most recent call last):
519
...
520
IndexError: UnsignedInfinityRing only has one generator
521
"""
522
if n == 0:
523
try:
524
return self._gen
525
except AttributeError:
526
self._gen = UnsignedInfinity()
527
return self._gen
528
else:
529
raise IndexError, "UnsignedInfinityRing only has one generator"
530
531
def gens(self):
532
"""
533
The "generator" of self is the infinity object.
534
535
EXAMPLES::
536
537
sage: UnsignedInfinityRing.gens()
538
[Infinity]
539
"""
540
return [self.gen()]
541
542
def less_than_infinity(self):
543
"""
544
This is the element that represents a finite value.
545
546
EXAMPLES::
547
548
sage: UnsignedInfinityRing.less_than_infinity()
549
A number less than infinity
550
sage: UnsignedInfinityRing(5) is UnsignedInfinityRing.less_than_infinity()
551
True
552
"""
553
try:
554
return self._less_than_infinity
555
except AttributeError:
556
self._less_than_infinity = LessThanInfinity(self)
557
return self._less_than_infinity
558
559
def _repr_(self):
560
"""
561
TESTS::
562
563
sage: UnsignedInfinityRing._repr_()
564
'The Unsigned Infinity Ring'
565
"""
566
return "The Unsigned Infinity Ring"
567
568
def __cmp__(self, right):
569
"""
570
TESTS::
571
572
sage: infinity == UnsignedInfinityRing.gen()
573
True
574
sage: UnsignedInfinityRing(3) == UnsignedInfinityRing(-19.5)
575
True
576
"""
577
if isinstance(right, UnsignedInfinityRing_class):
578
return 0
579
return cmp(type(self), type(right))
580
581
def _element_constructor_(self, x):
582
"""
583
TESTS::
584
585
sage: UnsignedInfinityRing(2)
586
A number less than infinity
587
sage: UnsignedInfinityRing(I)
588
A number less than infinity
589
sage: UnsignedInfinityRing(infinity)
590
Infinity
591
"""
592
if isinstance(x, InfinityElement):
593
if x.parent() is self:
594
return x
595
else:
596
return self.gen()
597
elif isinstance(x, RingElement) or isinstance(x, (int,long,float,complex)):
598
return self.less_than_infinity()
599
else:
600
raise TypeError
601
602
def _coerce_map_from_(self, R):
603
"""
604
EXAMPLES::
605
606
sage: UnsignedInfinityRing.has_coerce_map_from(int)
607
True
608
sage: UnsignedInfinityRing.has_coerce_map_from(CC)
609
True
610
sage: UnsignedInfinityRing.has_coerce_map_from(QuadraticField(-163, 'a'))
611
True
612
sage: UnsignedInfinityRing.has_coerce_map_from(QQ^3)
613
False
614
sage: UnsignedInfinityRing.has_coerce_map_from(SymmetricGroup(13))
615
False
616
"""
617
return isinstance(R, Ring) or R in (int, long, float, complex)
618
619
UnsignedInfinityRing = UnsignedInfinityRing_class()
620
621
class LessThanInfinity(_uniq, RingElement):
622
def __init__(self, parent=UnsignedInfinityRing):
623
"""
624
EXAMPLES::
625
626
sage: sage.rings.infinity.LessThanInfinity() is UnsignedInfinityRing(5)
627
True
628
"""
629
RingElement.__init__(self, parent)
630
631
def _repr_(self):
632
"""
633
EXAMPLES::
634
635
sage: UnsignedInfinityRing(5)._repr_()
636
'A number less than infinity'
637
"""
638
return "A number less than infinity"
639
640
def _latex_(self):
641
"""
642
EXAMPLES::
643
644
sage: UnsignedInfinityRing(5)._latex_()
645
'(<\\infty)'
646
"""
647
return "(<\\infty)"
648
649
def _add_(self, other):
650
"""
651
EXAMPLES::
652
653
sage: UnsignedInfinityRing(5) + UnsignedInfinityRing(-3)
654
A number less than infinity
655
sage: UnsignedInfinityRing(5) + unsigned_infinity
656
Infinity
657
"""
658
if isinstance(other, UnsignedInfinity):
659
return other
660
return self
661
662
def _sub_(self, other):
663
"""
664
EXAMPLES::
665
666
sage: UnsignedInfinityRing(5) - UnsignedInfinityRing(-3)
667
A number less than infinity
668
sage: UnsignedInfinityRing(5) - unsigned_infinity
669
Infinity
670
"""
671
if isinstance(other, UnsignedInfinity):
672
return other
673
return self
674
675
def _mul_(self, other):
676
"""
677
EXAMPLES::
678
679
sage: UnsignedInfinityRing(4) * UnsignedInfinityRing(-3)
680
A number less than infinity
681
sage: 5 * unsigned_infinity
682
Traceback (most recent call last):
683
...
684
ValueError: oo times number < oo not defined
685
sage: unsigned_infinity * unsigned_infinity
686
Infinity
687
"""
688
if isinstance(other, UnsignedInfinity):
689
raise ValueError, "oo times number < oo not defined"
690
return self
691
692
def _div_(self, other):
693
"""
694
Can't eliminate possibility of zero division....
695
696
EXAMPLES::
697
698
sage: UnsignedInfinityRing(2) / UnsignedInfinityRing(5)
699
Traceback (most recent call last):
700
...
701
ValueError: quotient of number < oo by number < oo not defined
702
sage: 1 / unsigned_infinity
703
0
704
"""
705
if isinstance(other, UnsignedInfinity):
706
return ZZ(0)
707
raise ValueError, "quotient of number < oo by number < oo not defined"
708
709
def __cmp__(self, other):
710
"""
711
EXAMPLES::
712
713
sage: 1 == unsigned_infinity
714
False
715
"""
716
if isinstance(other, UnsignedInfinity):
717
return -1
718
return 0
719
720
721
class UnsignedInfinity(_uniq, AnInfinity, InfinityElement):
722
723
_sign = 0
724
_sign_char = ''
725
726
def __init__(self):
727
"""
728
TESTS::
729
730
sage: sage.rings.infinity.UnsignedInfinity() is sage.rings.infinity.UnsignedInfinity() is unsigned_infinity
731
True
732
"""
733
InfinityElement.__init__(self, UnsignedInfinityRing)
734
735
def _mul_(self, other):
736
"""
737
Can't rule out an attempt at multiplication by 0.
738
739
EXAMPLES::
740
741
sage: unsigned_infinity * unsigned_infinity
742
Infinity
743
sage: unsigned_infinity * 0
744
Traceback (most recent call last):
745
...
746
ValueError: unsigned oo times smaller number not defined
747
sage: unsigned_infinity * 3
748
Traceback (most recent call last):
749
...
750
ValueError: unsigned oo times smaller number not defined
751
"""
752
if isinstance(other, UnsignedInfinity):
753
return self
754
raise ValueError, "unsigned oo times smaller number not defined"
755
756
757
unsigned_infinity = UnsignedInfinityRing.gen(0)
758
less_than_infinity = UnsignedInfinityRing.less_than_infinity()
759
760
def is_Infinite(x):
761
"""
762
This is a type check for infinity elements.
763
764
EXAMPLES::
765
766
sage: sage.rings.infinity.is_Infinite(oo)
767
True
768
sage: sage.rings.infinity.is_Infinite(-oo)
769
True
770
sage: sage.rings.infinity.is_Infinite(unsigned_infinity)
771
True
772
sage: sage.rings.infinity.is_Infinite(3)
773
False
774
sage: sage.rings.infinity.is_Infinite(RR(infinity))
775
False
776
sage: sage.rings.infinity.is_Infinite(ZZ)
777
False
778
"""
779
return isinstance(x, InfinityElement)
780
781
class SignError(Exception):
782
pass
783
784
class InfinityRing_class(_uniq, Ring):
785
def __init__(self):
786
"""
787
TEST::
788
789
sage: sage.rings.infinity.InfinityRing_class() is sage.rings.infinity.InfinityRing_class() is InfinityRing
790
True
791
"""
792
ParentWithGens.__init__(self, self, names=('oo',), normalize=False)
793
794
def fraction_field(self):
795
"""
796
This isn't really a ring, let alone an integral domain.
797
798
TEST::
799
800
sage: InfinityRing.fraction_field()
801
Traceback (most recent call last):
802
...
803
TypeError: infinity 'ring' has no fraction field
804
"""
805
raise TypeError, "infinity 'ring' has no fraction field"
806
807
def ngens(self):
808
"""
809
The two generators are plus and minus infinity.
810
811
EXAMPLES::
812
813
sage: InfinityRing.ngens()
814
2
815
sage: len(InfinityRing.gens())
816
2
817
"""
818
return 2
819
820
def gen(self, n=0):
821
"""
822
The two generators are plus and minus infinity.
823
824
EXAMPLES::
825
826
sage: InfinityRing.gen(0)
827
+Infinity
828
sage: InfinityRing.gen(1)
829
-Infinity
830
sage: InfinityRing.gen(2)
831
Traceback (most recent call last):
832
...
833
IndexError: n must be 0 or 1
834
"""
835
try:
836
if n == 0:
837
return self._gen0
838
elif n == 1:
839
return self._gen1
840
else:
841
raise IndexError, "n must be 0 or 1"
842
except AttributeError:
843
if n == 0:
844
self._gen0 = PlusInfinity()
845
return self._gen0
846
elif n == 1:
847
self._gen1 = MinusInfinity()
848
return self._gen1
849
850
def gens(self):
851
"""
852
The two generators are plus and minus infinity.
853
854
EXAMPLES::
855
856
sage: InfinityRing.gens()
857
[+Infinity, -Infinity]
858
"""
859
return [self.gen(0), self.gen(1)]
860
861
def _repr_(self):
862
"""
863
TEST::
864
865
sage: InfinityRing._repr_()
866
'The Infinity Ring'
867
"""
868
return "The Infinity Ring"
869
870
def __cmp__(self, right):
871
"""
872
TESTS::
873
874
sage: InfinityRing == InfinityRing
875
True
876
sage: InfinityRing == UnsignedInfinityRing
877
False
878
"""
879
if isinstance(right, InfinityRing_class):
880
return 0
881
return cmp(type(self), type(right))
882
883
def _element_constructor_(self, x):
884
"""
885
TESTS::
886
887
sage: InfinityRing(-oo)
888
-Infinity
889
sage: InfinityRing(3)
890
A positive finite number
891
sage: InfinityRing(-1.5)
892
A negative finite number
893
sage: [InfinityRing(a) for a in [-2..2]]
894
[A negative finite number, A negative finite number, Zero, A positive finite number, A positive finite number]
895
sage: K.<a> = QuadraticField(3)
896
sage: InfinityRing(a)
897
A positive finite number
898
sage: InfinityRing(a - 2)
899
A negative finite number
900
"""
901
if isinstance(x, PlusInfinityElement):
902
return self.gen(0)
903
elif isinstance(x, MinusInfinityElement):
904
return self.gen(1)
905
elif isinstance(x, InfinityElement):
906
return self.gen(0)
907
elif (isinstance(x, (sage.rings.integer.Integer,
908
sage.rings.rational.Rational,
909
sage.rings.real_double.RealDoubleElement,
910
sage.rings.real_mpfr.RealNumber))
911
or isinstance(x, (int,long,float))
912
or sage.rings.real_mpfr.RealField(sage.rings.real_mpfr.mpfr_prec_min())(x)):
913
if x < 0:
914
return FiniteNumber(self, -1)
915
elif x > 0:
916
return FiniteNumber(self, 1)
917
elif x == 0:
918
return FiniteNumber(self, 0)
919
else:
920
raise TypeError
921
else:
922
raise TypeError
923
924
def _coerce_map_from_(self, R):
925
"""
926
There is a coercion from anything that has a coercion into the reals.
927
928
EXAMPLES::
929
930
sage: InfinityRing.has_coerce_map_from(int)
931
True
932
sage: InfinityRing.has_coerce_map_from(AA)
933
True
934
sage: InfinityRing.has_coerce_map_from(RDF)
935
True
936
sage: InfinityRing.has_coerce_map_from(CC)
937
False
938
"""
939
return sage.rings.real_mpfr.RealField(sage.rings.real_mpfr.mpfr_prec_min()).has_coerce_map_from(R)
940
941
class FiniteNumber(RingElement):
942
def __init__(self, parent, x):
943
"""
944
TESTS::
945
946
sage: sage.rings.infinity.FiniteNumber(InfinityRing, 1)
947
A positive finite number
948
sage: sage.rings.infinity.FiniteNumber(InfinityRing, -1)
949
A negative finite number
950
sage: sage.rings.infinity.FiniteNumber(InfinityRing, 0)
951
Zero
952
"""
953
RingElement.__init__(self, parent)
954
self.value = x
955
956
def __cmp__(self, other):
957
"""
958
EXAMPLES::
959
960
sage: P = InfinityRing
961
sage: -oo < P(-5) < P(0) < P(1.5) < oo
962
True
963
sage: P(1) < P(100)
964
False
965
sage: P(-1) == P(-100)
966
True
967
"""
968
if isinstance(other, PlusInfinity):
969
return -1
970
if isinstance(other, MinusInfinity):
971
return 1
972
return cmp(self.value, other.value)
973
974
def _add_(self, other):
975
"""
976
EXAMPLES::
977
978
sage: P = InfinityRing
979
sage: 4 + oo
980
+Infinity
981
sage: P(4) + P(2)
982
A positive finite number
983
sage: P(-1) + P(1)
984
Traceback (most recent call last):
985
...
986
SignError: cannot add positive finite value to negative finite value
987
"""
988
if isinstance(other, InfinityElement):
989
return other
990
if self.value * other.value < 0:
991
raise SignError, "cannot add positive finite value to negative finite value"
992
return FiniteNumber(self.parent(), self.value)
993
994
def _mul_(self, other):
995
"""
996
EXAMPLES::
997
998
sage: P = InfinityRing
999
sage: 0 * oo
1000
Traceback (most recent call last):
1001
...
1002
SignError: cannot multiply infinity by zero
1003
sage: -1 * oo
1004
-Infinity
1005
sage: -2 * oo
1006
-Infinity
1007
sage: 3 * oo
1008
+Infinity
1009
sage: -oo * oo
1010
-Infinity
1011
sage: P(0) * 3
1012
0
1013
sage: P(-3) * P(2/3)
1014
A negative finite number
1015
"""
1016
if other.is_zero():
1017
if isinstance(self, InfinityElement):
1018
raise SignError, "cannot multiply infinity by zero"
1019
return ZZ(0)
1020
if self.value < 0:
1021
if isinstance(other, InfinityElement):
1022
return -other
1023
return FiniteNumber(self.parent(), self.value * other.value)
1024
if self.value > 0:
1025
if isinstance(other, InfinityElement):
1026
return other
1027
return FiniteNumber(self.parent(), self.value * other.value)
1028
if self.value == 0:
1029
if isinstance(other, InfinityElement):
1030
raise SignError, "cannot multiply infinity by zero"
1031
return ZZ(0)
1032
1033
def _div_(self, other):
1034
"""
1035
EXAMPLES::
1036
1037
sage: P = InfinityRing
1038
sage: 1 / oo
1039
0
1040
sage: oo / 4
1041
+Infinity
1042
sage: oo / -4
1043
-Infinity
1044
sage: P(1) / P(-4)
1045
A negative finite number
1046
"""
1047
return self * ~other
1048
1049
def _sub_(self, other):
1050
"""
1051
EXAMPLES::
1052
1053
sage: P = InfinityRing
1054
sage: 4 - oo
1055
-Infinity
1056
sage: 5 - -oo
1057
+Infinity
1058
sage: P(44) - P(4)
1059
Traceback (most recent call last):
1060
...
1061
SignError: cannot add positive finite value to negative finite value
1062
sage: P(44) - P(-1)
1063
A positive finite number
1064
"""
1065
return self._add_(-other)
1066
1067
def __invert__(self):
1068
"""
1069
EXAMPLES::
1070
1071
sage: P = InfinityRing
1072
sage: ~P(2)
1073
A positive finite number
1074
sage: ~P(-7)
1075
A negative finite number
1076
sage: ~P(0)
1077
Traceback (most recent call last):
1078
...
1079
ZeroDivisionError: Cannot divide by zero
1080
"""
1081
if self.value == 0:
1082
raise ZeroDivisionError, "Cannot divide by zero"
1083
return self
1084
1085
def _neg_(self):
1086
"""
1087
EXAMPLES::
1088
1089
sage: a = InfinityRing(5); a
1090
A positive finite number
1091
sage: -a
1092
A negative finite number
1093
sage: -(-a) == a
1094
True
1095
sage: -InfinityRing(0)
1096
Zero
1097
"""
1098
return FiniteNumber(self.parent(), -self.value)
1099
1100
def _repr_(self):
1101
"""
1102
EXAMPLES::
1103
1104
sage: InfinityRing(-2)._repr_()
1105
'A negative finite number'
1106
sage: InfinityRing(7)._repr_()
1107
'A positive finite number'
1108
sage: InfinityRing(0)._repr_()
1109
'Zero'
1110
"""
1111
if self.value < 0:
1112
return "A negative finite number"
1113
if self.value > 0:
1114
return "A positive finite number"
1115
return "Zero"
1116
1117
def _latex_(self):
1118
"""
1119
TESTS::
1120
1121
sage: a = InfinityRing(pi); a
1122
A positive finite number
1123
sage: a._latex_()
1124
'A positive finite number'
1125
sage: [latex(InfinityRing(a)) for a in [-2..2]]
1126
[A negative finite number, A negative finite number, Zero, A positive finite number, A positive finite number]
1127
"""
1128
return self._repr_()
1129
1130
def __abs__(self):
1131
"""
1132
EXAMPLES::
1133
1134
sage: abs(InfinityRing(-3))
1135
A positive finite number
1136
sage: abs(InfinityRing(3))
1137
A positive finite number
1138
sage: abs(InfinityRing(0))
1139
Zero
1140
"""
1141
if self.value == 0:
1142
return FiniteNumber(self.parent(), 0)
1143
return FiniteNumber(self.parent(), 1)
1144
1145
def sqrt(self):
1146
"""
1147
EXAMPLES::
1148
1149
sage: InfinityRing(7).sqrt()
1150
A positive finite number
1151
sage: InfinityRing(0).sqrt()
1152
Zero
1153
sage: InfinityRing(-.001).sqrt()
1154
Traceback (most recent call last):
1155
...
1156
SignError: cannot take square root of a negative number
1157
"""
1158
if self.value < 0:
1159
raise SignError, "cannot take square root of a negative number"
1160
return self
1161
1162
class MinusInfinity(_uniq, AnInfinity, MinusInfinityElement):
1163
1164
_sign = -1
1165
_sign_char = '-'
1166
1167
def __init__(self):
1168
"""
1169
TESTS::
1170
1171
sage: sage.rings.infinity.MinusInfinity() is sage.rings.infinity.MinusInfinity() is -oo
1172
True
1173
"""
1174
InfinityElement.__init__(self, InfinityRing)
1175
1176
def _neg_(self):
1177
"""
1178
EXAMPLES::
1179
1180
sage: -(-oo)
1181
+Infinity
1182
"""
1183
return self.parent().gen(0)
1184
1185
def sqrt(self):
1186
"""
1187
EXAMPLES::
1188
1189
sage: (-oo).sqrt()
1190
Traceback (most recent call last):
1191
...
1192
SignError: cannot take square root of negative infinity
1193
"""
1194
raise SignError, "cannot take square root of negative infinity"
1195
1196
def _sympy_(self):
1197
"""
1198
Converts -oo to sympy -oo.
1199
1200
Then you don't have to worry which oo you use, like in these
1201
examples:
1202
1203
EXAMPLE::
1204
1205
sage: import sympy
1206
sage: bool(-oo == -sympy.oo)
1207
True
1208
sage: bool(SR(-oo) == -sympy.oo)
1209
True
1210
sage: bool((-oo)._sympy_() == -sympy.oo)
1211
True
1212
1213
"""
1214
import sympy
1215
return -sympy.oo
1216
1217
1218
class PlusInfinity(_uniq, AnInfinity, PlusInfinityElement):
1219
1220
_sign = 1
1221
_sign_char = '+'
1222
1223
def __init__(self):
1224
"""
1225
TESTS::
1226
1227
sage: sage.rings.infinity.PlusInfinity() is sage.rings.infinity.PlusInfinity() is oo
1228
True
1229
"""
1230
InfinityElement.__init__(self, InfinityRing)
1231
1232
def _neg_(self):
1233
"""
1234
TESTS::
1235
1236
sage: -oo
1237
-Infinity
1238
"""
1239
return self.parent().gen(1)
1240
1241
def sqrt(self):
1242
"""
1243
EXAMPLES::
1244
1245
sage: oo.sqrt()
1246
+Infinity
1247
"""
1248
return self
1249
1250
def _sympy_(self):
1251
"""
1252
Converts oo to sympy oo.
1253
1254
Then you don't have to worry which oo you use, like in these
1255
examples:
1256
1257
EXAMPLE::
1258
1259
sage: import sympy
1260
sage: bool(oo == sympy.oo) # indirect doctest
1261
True
1262
sage: bool(SR(oo) == sympy.oo)
1263
True
1264
"""
1265
import sympy
1266
return sympy.oo
1267
1268
InfinityRing = InfinityRing_class()
1269
infinity = InfinityRing.gen(0)
1270
Infinity = infinity
1271
minus_infinity = InfinityRing.gen(1)
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289