Revision 3311:adf6ac965ebd, 16.3 KB checked in by David Roe <roed@…>, 6 years ago (diff)

Line
1r"""
2Infinity Rings
3
4The unsigned infinity ring'' is the set of two elements
5\begin{verbatim}
6        * infinity
7        * A number less than infinity
8\end{verbatim}
9
10The rules for arithmetic are that the unsigned infinity ring does not canonically
11coerce to any other ring, and all other rings canonically coerce to
12the unsigned infinity ring, sending all elements to the single element
13a number less than infinity'' of the unsigned infinity ring.
14Arithmetic and comparisons then takes place in the unsigned infinity ring,
15where all arithmetic operations that are well defined are defined.
16
17The infinity ring'' is the set of five elements
18\begin{verbatim}
19        * plus infinity
20        * a positive finite element
21        * zero
22        * a negative finite element
23        * negative infinity
24\end{verbatim}
25
26The infinity ring coerces to the unsigned infinity ring, sending the infinite elements to infinity and the non-infinite elements to a number less than infinity.''  Any ordered ring coerces to the infinity ring in the obvious way.
27
28EXAMPLES:
29We fetch the unsigned infinity ring and create some elements:
30    sage: P = UnsignedInfinityRing; P
31    The Unsigned Infinity Ring
32    sage: P(5)
33    A number less than infinity
34    sage: P.ngens()
35    1
36    sage: oo = P.0; oo
37    Infinity
38
39We compare finite numbers with infinity.
40    sage: 5 < oo
41    True
42    sage: 5 > oo
43    False
44    sage: oo < 5
45    False
46    sage: oo > 5
47    True
48
49We do arithmetic.
50    sage: oo + 5
51    Infinity
52
53Note that many operations are not defined, since the result is
54not well defined.
55    sage: oo/0
56    Traceback (most recent call last):
57    ...
58    TypeError: unsupported operand parent(s) for '/': 'The Unsigned Infinity Ring' and 'Integer Ring'
59
60What happened above is that 0 is canonically coerced to
61"a number less than infinity" in the unsigned infinity ring, and the quotient
62is then not well defined.
63
64    sage: 0/oo
65    A number less than infinity
66    sage: oo * 0
67    Traceback (most recent call last):
68    ...
69    TypeError: unsupported operand parent(s) for '*': 'The Unsigned Infinity Ring' and 'The Unsigned Infinity Ring'
70    sage: oo/oo
71    Traceback (most recent call last):
72    ...
73    TypeError: unsupported operand parent(s) for '/': 'The Unsigned Infinity Ring' and 'The Unsigned Infinity Ring'
74
75In the infinity ring, we can negate infinity, multiply positive numbers by infinity, etc.
76    sage: P = InfinityRing; P
77    The Infinity Ring
78    sage: P(5)
79    A positive finite number
80    sage: oo = P.0; oo
81    +Infinity
82
83We compare finite and infinite elements
84    sage: 5 < oo
85    True
86    sage: P(-5) < P(5)
87    True
88    sage: P(2) < P(3)
89    False
90    sage: -oo < oo
91    True
92
93We can do more arithmetic than in the unsigned infinity ring.
94    sage: 2 * oo
95    +Infinity
96    sage: -2 * oo
97    -Infinity
98    sage: 1 - oo
99    -Infinity
100    sage: 1 / oo
101    Zero
102    sage: -1 / oo
103    Zero
104
105If we try to subtract infinities or multiply infinity by zero we still get an error.
106    sage: oo - oo
107    Traceback (most recent call last):
108    ...
109    SignError: cannot add infinity to minus infinity
110    sage: 0 * oo
111    Traceback (most recent call last):
112    ...
113    SignError: cannot multiply infinity by zero
114    sage: P(2) + P(-3)
115    Traceback (most recent call last):
116    ...
117    SignError: cannot add positive finite value to negative finite value
118"""
119
120from sage.rings.ring_element import RingElement
121from sage.rings.ring import Ring
122from sage.structure.element import RingElement, InfinityElement
123from sage.structure.parent_gens import ParentWithGens
124#import sage.rings.real_double
125#import sage.rings.real_mpfr
126import sage.rings.integer
127import sage.rings.rational
128
129_obj = {}
130class _uniq0(object):
131    def __new__(cls):
132        if _obj.has_key(0):
133            return _obj[0]
134        O = Ring.__new__(cls)
135        _obj[0] = O
136        return O
137class _uniq1(object):
138    def __new__(cls):
139        if _obj.has_key(1):
140            return _obj[1]
141        O = InfinityElement.__new__(cls)
142        _obj[1] = O
143        return O
144class _uniq2(object):
145    def __new__(cls):
146        if _obj.has_key(2):
147            return _obj[2]
148        O = Ring.__new__(cls)
149        _obj[2] = O
150        return O
151class _uniq3(object):
152    def __new__(cls):
153        if _obj.has_key(3):
154            return _obj[3]
155        O = InfinityElement.__new__(cls)
156        _obj[3] = O
157        return O
158class _uniq4(object):
159    def __new__(cls):
160        if _obj.has_key(4):
161            return _obj[4]
162        O = InfinityElement.__new__(cls)
163        _obj[4] = O
164        return O
165
166class UnsignedInfinityRing_class(_uniq0, Ring):
167    def __init__(self):
168        ParentWithGens.__init__(self, self, names=('oo',), normalize=False)
169
170    def ngens(self):
171        return 1
172
173    def gen(self, n=0):
174        try:
175            return self._gen
176        except AttributeError:
177            self._gen = UnsignedInfinity()
178        return self._gen
179
180    def less_than_infinity(self):
181        try:
182            return self._less_than_infinity
183        except AttributeError:
184            self._less_than_infinity = LessThanInfinity(self)
185            return self._less_than_infinity
186
187    def gens(self):
188        return [self.gen()]
189
190    def _repr_(self):
191        return "The Unsigned Infinity Ring"
192
193    def __cmp__(self, right):
194        if isinstance(right, UnsignedInfinityRing_class):
195            return 0
196        return cmp(type(self), type(right))
197
198    def __call__(self, x):
199        if isinstance(x, InfinityElement):
200            if x.parent() is self:
201                return x
202            else:
203                return self.gen()
204        elif isinstance(x, RingElement) or isinstance(x, (int,long,float,complex)):
205            return self.less_than_infinity()
206        else:
207            raise TypeError
208
209    def _coerce_impl(self, x):
210        if isinstance(x, InfinityElement):
211            x = UnsignedInfinity()
212            x._set_parent(self)
213            return x
214        elif isinstance(x, RingElement):
215            return less_than_infinity
216        else:
217            raise TypeError
218
219UnsignedInfinityRing = UnsignedInfinityRing_class()
220
221class LessThanInfinity(RingElement):
222    def __init__(self, parent=UnsignedInfinityRing):
223        RingElement.__init__(self, parent)
224
225    def _repr_(self):
226        return "A number less than infinity"
227
228    def _latex_(self):
229        return "(<\\infty)"
230
232        if isinstance(other, UnsignedInfinity):
233            return other
234        return self
235
236    def _sub_(self, other):
237        if isinstance(other, UnsignedInfinity):
238            return other
239        return self
240
241    def _mul_(self, other):
242        if isinstance(other, UnsignedInfinity):
243            raise TypeError, "oo times number < oo not defined"
244        return self
245
246    def _div_(self, other):
247        if isinstance(other, UnsignedInfinity):
248            return self
249        raise TypeError, "quotient of oo by number < oo not defined"
250
251    def __cmp__(self, other):
252        if isinstance(other, UnsignedInfinity):
253            return -1
254        return 0
255
256
257class UnsignedInfinity(_uniq1, InfinityElement):
258    def __init__(self):
259        InfinityElement.__init__(self, UnsignedInfinityRing)
260
261    def _repr_(self):
262        return "Infinity"
263
264    def lcm(self, x):
265        """
266        Return the least common multiple of oo and x, which
267        is by definition oo unless x is 0.
268
269        EXAMPLES:
270            sage: oo = UnsignedInfinityRing.gen(0)
271            sage: oo.lcm(0)
272            0
273            sage: oo.lcm(oo)
274            Infinity
275            sage: oo.lcm(10)
276            Infinity
277        """
278        if x == 0:
279            return x
280        else:
281            return self
282
283    def _latex_(self):
284        return "\\infty"
285
287        return self
288
289    def _sub_(self, other):
290        if not isinstance(other, UnsignedInfinity):
291            return self
292        raise TypeError, "oo - oo not defined"
293
294    def _mul_(self, other):
295        if isinstance(other, UnsignedInfinity):
296            return self
297        raise TypeError, "oo times smaller number not defined"
298
299    def __cmp__(self, other):
300        if isinstance(other, UnsignedInfinity):
301            return 0
302        return 1
303
304
305unsigned_infinity = UnsignedInfinityRing.gen(0)
306less_than_infinity = UnsignedInfinityRing.less_than_infinity()
307
308def is_Infinite(x):
309    return isinstance(x, InfinityElement)
310
311class SignError(Exception):
312    pass
313
314class InfinityRing_class(_uniq2, Ring):
315    def __init__(self):
316        ParentWithGens.__init__(self, self, names=('oo',), normalize=False)
317
318    def ngens(self):
319        return 1
320
321    def gen(self, n=0):
322        try:
323            if n == 0:
324                return self._gcd0
325            elif n == 1:
326                return self._gcd1
327            else:
328                raise IndexError, "n must be 0 or 1"
329        except AttributeError:
330            if n == 0:
331                self._gen0 = PlusInfinity()
332                return self._gen0
333            elif n == 1:
334                self._gen1 = MinusInfinity()
335                return self._gen1
336
337    def gens(self):
338        return [self.gen(0), self.gen(1)]
339
340    def _repr_(self):
341        return "The Infinity Ring"
342
343    def __cmp__(self, right):
344        if isinstance(right, InfinityRing_class):
345            return 0
346        return cmp(type(self), type(right))
347
348    def __call__(self, x):
349        if isinstance(x, PlusInfinity):
350            return self.gen(0)
351        elif isinstance(x, MinusInfinity):
352            return self.gen(1)
353        elif isinstance(x, InfinityElement):
354            return self.gen(0)
355        elif isinstance(x, (sage.rings.integer.Integer, sage.rings.rational.Rational, sage.rings.real_double.RealDoubleElement, sage.rings.real_mpfr.RealNumber)) or isinstance(x, (int,long,float)):
356            if x < 0:
357                return FiniteNumber(self, -1)
358            elif x > 0:
359                return FiniteNumber(self, 1)
360            else:
361                return FiniteNumber(self, 0)
362        else:
363            raise TypeError
364
365    def _coerce_impl(self, x):
366        if isinstance(x, PlusInfinity):
367            if x.parent() is self:
368                return x
369            else:
370                return self.gen()
371        elif isinstance(x, MinusInfinity):
372            if x.parent() is self:
373                return x
374            else:
375                return -self.gen()
376        elif isinstance(x, (sage.rings.integer.Integer, sage.rings.rational.Rational, sage.rings.real_double.RealDoubleElement, sage.rings.real_mpfr.RealNumber)) or isinstance(x, (int,long,float)):
377        #elif isinstance(x, (sage.rings.integer.Integer, sage.rings.rational.Rational)) or isinstance(x, (int,long,float)):
378            if x < 0:
379                return FiniteNumber(self, -1)
380            elif x > 0:
381                return FiniteNumber(self, 1)
382            else:
383                return FiniteNumber(self, 0)
384        else:
385            raise TypeError
386
387class FiniteNumber(RingElement):
388    def __init__(self, parent, x):
389        RingElement.__init__(self, parent)
390        self.value = x
391
392    def __cmp__(self, other):
393        if isinstance(other, PlusInfinity):
394            return -1
395        if isinstance(other, MinusInfinity):
396            return 1
397        return self.value.__cmp__(other.value)
398
400        if isinstance(other, InfinityElement):
401            return other
402        if self.value * other.value < 0:
403            raise SignError, "cannot add positive finite value to negative finite value"
404        return FiniteNumber(self.parent(), self.value)
405
406    def _mul_(self, other):
407        if self.value < 0:
408            if isinstance(other, InfinityElement):
409                return -other
410            return FiniteNumber(self.parent(), self.value * other.value)
411        if self.value > 0:
412            if isinstance(other, InfinityElement):
413                return other
414            return FiniteNumber(self.parent(), self.value * other.value)
415        if self.value == 0:
416            if isinstance(other, InfinityElement):
417                raise SignError, "cannot multiply infinity by zero"
418            return FiniteNumber(self.parent(), 0)
419
420    def _div_(self, other):
421        return self._mul_(other.__invert__())
422
423    def _sub_(self, other):
425
426    def __invert__(self):
427        if self.value == 0:
428            raise ZeroDivisionError, "Cannot divide by zero"
429        return self
430
431    def _neg_(self):
432        return FiniteNumber(self.parent(), -self.value)
433
434    def __repr__(self):
435        if self.value < 0:
436            return "A negative finite number"
437        if self.value > 0:
438            return "A positive finite number"
439        return "Zero"
440
441    def _latex_(self):
442        return self.__repr__()
443
444    def __abs__(self):
445        if self.value == 0:
446            return FiniteNumber(self.parent(), 0)
447        return FiniteNumber(self.parent(), 1)
448
449    def sqrt(self):
450        if self._value < 0:
451            raise SignError, "cannot take square root of a negative number"
452        return self
453
454    def square_root(self):
455        if self._value < 0:
456            raise SignError, "cannot take square root of a negative number"
457        return self
458
459class MinusInfinity(_uniq3, InfinityElement):
460    def __init__(self):
461        InfinityElement.__init__(self, InfinityRing)
462
463    def __cmp__(self, other):
464        if isinstance(other, MinusInfinity):
465            return 0
466        return -1
467
468    def __repr__(self):
469        return "-Infinity"
470
471    def _latex_(self):
472        return "-\\infty"
473
475        if isinstance(other, PlusInfinity):
476            raise SignError, "cannot add infinity to minus infinity"
477        return self
478
479    def _mul_(self, other):
480        if other < 0:
481            return -self
482        if other > 0:
483            return self
484        raise SignError, "cannot multiply infinity by zero"
485
486    def _sub_(self, other):
487        if isinstance(other, MinusInfinity):
488            raise SignError, "cannot add infinity to minus infinity"
489        return self
490
491    def _div_(self, other):
492        return self * other.__invert__()
493
494    def _neg_(self):
495        return self.parent().gen(0)
496
497    def __invert__(self):
498        return FiniteNumber(self.parent(), 0)
499
500    def __abs__(self):
501        return self.parent().gen(0)
502
503    def lcm(self, x):
504        """
505        Return the least common multiple of -oo and x, which
506        is by definition oo unless x is 0.
507
508        EXAMPLES:
509            sage: moo = InfinityRing.gen(1)
510            sage: moo.lcm(0)
511            0
512            sage: moo.lcm(oo)
513            +Infinity
514            sage: moo.lcm(10)
515            +Infinity
516        """
517        if x == 0:
518            return x
519        else:
520            return -self
521
522    def sqrt(self):
523        raise SignError, "cannot take square root of negative infinity"
524
525    def square_root(self):
526        raise SignError, "cannot take square root of negative infinity"
527
528class PlusInfinity(_uniq4, InfinityElement):
529    def __init__(self):
530        InfinityElement.__init__(self, InfinityRing)
531
532    def __cmp__(self, other):
533        if isinstance(other, PlusInfinity):
534            return 0
535        return 1
536
537    def __repr__(self):
538        return "+Infinity"
539
540    def _latex_(self):
541        return "+\\infty"
542
544        if isinstance(other, MinusInfinity):
545            raise SignError, "cannot add infinity to minus infinity"
546        return self
547
548    def _mul_(self, other):
549        if other < 0:
550            return -self
551        if other > 0:
552            return self
553        raise TypeError, "cannot multiply infinity by zero"
554
555    def _sub_(self, other):
556        if isinstance(other, PlusInfinity):
557            raise SignError, "cannot add infinity to minus infinity"
558        return self
559
560    def _div_(self, other):
561        return self * other.__invert__()
562
563    def _neg_(self):
564        return self.parent().gen(1)
565
566    def __invert__(self):
567        return FiniteNumber(self.parent(), 0)
568
569    def __abs__(self):
570        return self
571
572    def lcm(self, x):
573        """
574        Return the least common multiple of oo and x, which
575        is by definition oo unless x is 0.
576
577        EXAMPLES:
578            sage: oo = InfinityRing.gen(0)
579            sage: oo.lcm(0)
580            0
581            sage: oo.lcm(oo)
582            +Infinity
583            sage: oo.lcm(10)
584            +Infinity
585        """
586        if x == 0:
587            return x
588        else:
589            return self
590
591    def sqrt(self):
592        return self
593
594    def square_root(self):
595        return self
596
597InfinityRing = InfinityRing_class()
598infinity = InfinityRing.gen(0)
599Infinity = infinity
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
Note: See TracBrowser for help on using the repository browser.