Signed and Unsigned Infinities

The unsigned infinity “ring” is the set of two elements

  1. infinity

  2. A number less than infinity

The rules for arithmetic are that the unsigned infinity ring does not canonically coerce to any other ring, and all other rings canonically coerce to the unsigned infinity ring, sending all elements to the single element “a number less than infinity” of the unsigned infinity ring. Arithmetic and comparisons then take place in the unsigned infinity ring, where all arithmetic operations that are well-defined are defined.

The infinity “ring” is the set of five elements

  1. plus infinity

  2. a positive finite element

  3. zero

  4. a negative finite element

  5. negative infinity

The 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.

Note

The shorthand oo is predefined in Sage to be the same as +Infinity in the infinity ring. It is considered equal to, but not the same as Infinity in the UnsignedInfinityRing.

EXAMPLES:

We fetch the unsigned infinity ring and create some elements:

sage: P = UnsignedInfinityRing; P
The Unsigned Infinity Ring
sage: P(5)
A number less than infinity
sage: P.ngens()
1
sage: unsigned_oo = P.0; unsigned_oo
Infinity
>>> from sage.all import *
>>> P = UnsignedInfinityRing; P
The Unsigned Infinity Ring
>>> P(Integer(5))
A number less than infinity
>>> P.ngens()
1
>>> unsigned_oo = P.gen(0); unsigned_oo
Infinity
P = UnsignedInfinityRing; P
P(5)
P.ngens()
unsigned_oo = P.0; unsigned_oo

We compare finite numbers with infinity:

sage: 5 < unsigned_oo
True
sage: 5 > unsigned_oo
False
sage: unsigned_oo < 5
False
sage: unsigned_oo > 5
True
>>> from sage.all import *
>>> Integer(5) < unsigned_oo
True
>>> Integer(5) > unsigned_oo
False
>>> unsigned_oo < Integer(5)
False
>>> unsigned_oo > Integer(5)
True
5 < unsigned_oo
5 > unsigned_oo
unsigned_oo < 5
unsigned_oo > 5

Demonstrating the shorthand oo versus Infinity:

sage: oo
+Infinity
sage: oo is InfinityRing.0
True
sage: oo is UnsignedInfinityRing.0
False
sage: oo == UnsignedInfinityRing.0
True
>>> from sage.all import *
>>> oo
+Infinity
>>> oo is InfinityRing.gen(0)
True
>>> oo is UnsignedInfinityRing.gen(0)
False
>>> oo == UnsignedInfinityRing.gen(0)
True
oo
oo is InfinityRing.0
oo is UnsignedInfinityRing.0
oo == UnsignedInfinityRing.0

We do arithmetic:

sage: unsigned_oo + 5
Infinity
>>> from sage.all import *
>>> unsigned_oo + Integer(5)
Infinity
unsigned_oo + 5

We make 1 / unsigned_oo return the integer 0 so that arithmetic of the following type works:

sage: (1/unsigned_oo) + 2
2
sage: 32/5 - (2.439/unsigned_oo)
32/5
>>> from sage.all import *
>>> (Integer(1)/unsigned_oo) + Integer(2)
2
>>> Integer(32)/Integer(5) - (RealNumber('2.439')/unsigned_oo)
32/5
(1/unsigned_oo) + 2
32/5 - (2.439/unsigned_oo)

Note that many operations are not defined, since the result is not well-defined:

sage: unsigned_oo/0
Traceback (most recent call last):
...
ValueError: quotient of number < oo by number < oo not defined
>>> from sage.all import *
>>> unsigned_oo/Integer(0)
Traceback (most recent call last):
...
ValueError: quotient of number < oo by number < oo not defined
unsigned_oo/0

What happened above is that 0 is canonically coerced to “A number less than infinity” in the unsigned infinity ring. Next, Sage tries to divide by multiplying with its inverse. Finally, this inverse is not well-defined.

sage: 0/unsigned_oo
0
sage: unsigned_oo * 0
Traceback (most recent call last):
...
ValueError: unsigned oo times smaller number not defined
sage: unsigned_oo/unsigned_oo
Traceback (most recent call last):
...
ValueError: unsigned oo times smaller number not defined
>>> from sage.all import *
>>> Integer(0)/unsigned_oo
0
>>> unsigned_oo * Integer(0)
Traceback (most recent call last):
...
ValueError: unsigned oo times smaller number not defined
>>> unsigned_oo/unsigned_oo
Traceback (most recent call last):
...
ValueError: unsigned oo times smaller number not defined
0/unsigned_oo
unsigned_oo * 0
unsigned_oo/unsigned_oo

In the infinity ring, we can negate infinity, multiply positive numbers by infinity, etc.

sage: P = InfinityRing; P
The Infinity Ring
sage: P(5)
A positive finite number
>>> from sage.all import *
>>> P = InfinityRing; P
The Infinity Ring
>>> P(Integer(5))
A positive finite number
P = InfinityRing; P
P(5)

The symbol oo is predefined as a shorthand for +Infinity:

sage: oo
+Infinity
>>> from sage.all import *
>>> oo
+Infinity
oo

We compare finite and infinite elements:

sage: 5 < oo
True
sage: P(-5) < P(5)
True
sage: P(2) < P(3)
False
sage: -oo < oo
True
>>> from sage.all import *
>>> Integer(5) < oo
True
>>> P(-Integer(5)) < P(Integer(5))
True
>>> P(Integer(2)) < P(Integer(3))
False
>>> -oo < oo
True
5 < oo
P(-5) < P(5)
P(2) < P(3)
-oo < oo

We can do more arithmetic than in the unsigned infinity ring:

sage: 2 * oo
+Infinity
sage: -2 * oo
-Infinity
sage: 1 - oo
-Infinity
sage: 1 / oo
0
sage: -1 / oo
0
>>> from sage.all import *
>>> Integer(2) * oo
+Infinity
>>> -Integer(2) * oo
-Infinity
>>> Integer(1) - oo
-Infinity
>>> Integer(1) / oo
0
>>> -Integer(1) / oo
0
2 * oo
-2 * oo
1 - oo
1 / oo
-1 / oo

We make 1 / oo and 1 / -oo return the integer 0 instead of the infinity ring Zero so that arithmetic of the following type works:

sage: (1/oo) + 2
2
sage: 32/5 - (2.439/-oo)
32/5
>>> from sage.all import *
>>> (Integer(1)/oo) + Integer(2)
2
>>> Integer(32)/Integer(5) - (RealNumber('2.439')/-oo)
32/5
(1/oo) + 2
32/5 - (2.439/-oo)

If we try to subtract infinities or multiply infinity by zero we still get an error:

sage: oo - oo
Traceback (most recent call last):
...
SignError: cannot add infinity to minus infinity
sage: 0 * oo
Traceback (most recent call last):
...
SignError: cannot multiply infinity by zero
sage: P(2) + P(-3)
Traceback (most recent call last):
...
SignError: cannot add positive finite value to negative finite value
>>> from sage.all import *
>>> oo - oo
Traceback (most recent call last):
...
SignError: cannot add infinity to minus infinity
>>> Integer(0) * oo
Traceback (most recent call last):
...
SignError: cannot multiply infinity by zero
>>> P(Integer(2)) + P(-Integer(3))
Traceback (most recent call last):
...
SignError: cannot add positive finite value to negative finite value
oo - oo
0 * oo
P(2) + P(-3)

Signed infinity can also be represented by RR / RDF elements. But unsigned infinity cannot:

sage: oo in RR, oo in RDF
(True, True)
sage: unsigned_infinity in RR, unsigned_infinity in RDF
(False, False)
>>> from sage.all import *
>>> oo in RR, oo in RDF
(True, True)
>>> unsigned_infinity in RR, unsigned_infinity in RDF
(False, False)
oo in RR, oo in RDF
unsigned_infinity in RR, unsigned_infinity in RDF
class sage.rings.infinity.AnInfinity[source]

Bases: object

lcm(x)[source]

Return the least common multiple of oo and x, which is by definition oo unless x is 0.

EXAMPLES:

sage: oo.lcm(0)
0
sage: oo.lcm(oo)
+Infinity
sage: oo.lcm(-oo)
+Infinity
sage: oo.lcm(10)
+Infinity
sage: (-oo).lcm(10)
+Infinity
>>> from sage.all import *
>>> oo.lcm(Integer(0))
0
>>> oo.lcm(oo)
+Infinity
>>> oo.lcm(-oo)
+Infinity
>>> oo.lcm(Integer(10))
+Infinity
>>> (-oo).lcm(Integer(10))
+Infinity
oo.lcm(0)
oo.lcm(oo)
oo.lcm(-oo)
oo.lcm(10)
(-oo).lcm(10)
class sage.rings.infinity.FiniteNumber(parent, x)[source]

Bases: RingElement

Initialize self.

sign()[source]

Return the sign of self.

EXAMPLES:

sage: sign(InfinityRing(2))
1
sage: sign(InfinityRing(0))
0
sage: sign(InfinityRing(-2))
-1
>>> from sage.all import *
>>> sign(InfinityRing(Integer(2)))
1
>>> sign(InfinityRing(Integer(0)))
0
>>> sign(InfinityRing(-Integer(2)))
-1
sign(InfinityRing(2))
sign(InfinityRing(0))
sign(InfinityRing(-2))
sqrt()[source]

EXAMPLES:

sage: InfinityRing(7).sqrt()
A positive finite number
sage: InfinityRing(0).sqrt()
Zero
sage: InfinityRing(-.001).sqrt()
Traceback (most recent call last):
...
SignError: cannot take square root of a negative number
>>> from sage.all import *
>>> InfinityRing(Integer(7)).sqrt()
A positive finite number
>>> InfinityRing(Integer(0)).sqrt()
Zero
>>> InfinityRing(-RealNumber('.001')).sqrt()
Traceback (most recent call last):
...
SignError: cannot take square root of a negative number
InfinityRing(7).sqrt()
InfinityRing(0).sqrt()
InfinityRing(-.001).sqrt()
class sage.rings.infinity.InfinityRing_class[source]

Bases: Singleton, CommutativeRing

Initialize self.

fraction_field()[source]

This isn’t really a ring, let alone an integral domain.

gen(n=0)[source]

The two generators are plus and minus infinity.

EXAMPLES:

sage: InfinityRing.gen(0)
+Infinity
sage: InfinityRing.gen(1)
-Infinity
sage: InfinityRing.gen(2)
Traceback (most recent call last):
...
IndexError: n must be 0 or 1
>>> from sage.all import *
>>> InfinityRing.gen(Integer(0))
+Infinity
>>> InfinityRing.gen(Integer(1))
-Infinity
>>> InfinityRing.gen(Integer(2))
Traceback (most recent call last):
...
IndexError: n must be 0 or 1
InfinityRing.gen(0)
InfinityRing.gen(1)
InfinityRing.gen(2)
gens()[source]

The two generators are plus and minus infinity.

EXAMPLES:

sage: InfinityRing.gens()
(+Infinity, -Infinity)
>>> from sage.all import *
>>> InfinityRing.gens()
(+Infinity, -Infinity)
InfinityRing.gens()
is_commutative()[source]

The Infinity Ring is commutative

EXAMPLES:

sage: InfinityRing.is_commutative()
True
>>> from sage.all import *
>>> InfinityRing.is_commutative()
True
InfinityRing.is_commutative()
is_zero()[source]

The Infinity Ring is not zero

EXAMPLES:

sage: InfinityRing.is_zero()
False
>>> from sage.all import *
>>> InfinityRing.is_zero()
False
InfinityRing.is_zero()
ngens()[source]

The two generators are plus and minus infinity.

EXAMPLES:

sage: InfinityRing.ngens()
2
sage: len(InfinityRing.gens())
2
>>> from sage.all import *
>>> InfinityRing.ngens()
2
>>> len(InfinityRing.gens())
2
InfinityRing.ngens()
len(InfinityRing.gens())
class sage.rings.infinity.LessThanInfinity(*args)[source]

Bases: _uniq, RingElement

Initialize self.

EXAMPLES:

sage: sage.rings.infinity.LessThanInfinity() is UnsignedInfinityRing(5)
True
>>> from sage.all import *
>>> sage.rings.infinity.LessThanInfinity() is UnsignedInfinityRing(Integer(5))
True
sage.rings.infinity.LessThanInfinity() is UnsignedInfinityRing(5)
sign()[source]

Raise an error because the sign of self is not well defined.

EXAMPLES:

sage: sign(UnsignedInfinityRing(2))
Traceback (most recent call last):
...
NotImplementedError: sign of number < oo is not well defined
sage: sign(UnsignedInfinityRing(0))
Traceback (most recent call last):
...
NotImplementedError: sign of number < oo is not well defined
sage: sign(UnsignedInfinityRing(-2))
Traceback (most recent call last):
...
NotImplementedError: sign of number < oo is not well defined
>>> from sage.all import *
>>> sign(UnsignedInfinityRing(Integer(2)))
Traceback (most recent call last):
...
NotImplementedError: sign of number < oo is not well defined
>>> sign(UnsignedInfinityRing(Integer(0)))
Traceback (most recent call last):
...
NotImplementedError: sign of number < oo is not well defined
>>> sign(UnsignedInfinityRing(-Integer(2)))
Traceback (most recent call last):
...
NotImplementedError: sign of number < oo is not well defined
sign(UnsignedInfinityRing(2))
sign(UnsignedInfinityRing(0))
sign(UnsignedInfinityRing(-2))
class sage.rings.infinity.MinusInfinity(*args)[source]

Bases: _uniq, AnInfinity, InfinityElement

Initialize self.

sqrt()[source]

EXAMPLES:

sage: (-oo).sqrt()
Traceback (most recent call last):
...
SignError: cannot take square root of negative infinity
>>> from sage.all import *
>>> (-oo).sqrt()
Traceback (most recent call last):
...
SignError: cannot take square root of negative infinity
(-oo).sqrt()
class sage.rings.infinity.PlusInfinity(*args)[source]

Bases: _uniq, AnInfinity, InfinityElement

Initialize self.

sqrt()[source]

The square root of self.

The square root of infinity is infinity.

EXAMPLES:

sage: oo.sqrt()
+Infinity
>>> from sage.all import *
>>> oo.sqrt()
+Infinity
oo.sqrt()
exception sage.rings.infinity.SignError[source]

Bases: ArithmeticError

Sign error exception.

class sage.rings.infinity.UnsignedInfinity(*args)[source]

Bases: _uniq, AnInfinity, InfinityElement

Initialize self.

class sage.rings.infinity.UnsignedInfinityRing_class[source]

Bases: Singleton, Parent

Initialize self.

gen(n=0)[source]

The “generator” of self is the infinity object.

EXAMPLES:

sage: UnsignedInfinityRing.gen()
Infinity
sage: UnsignedInfinityRing.gen(1)
Traceback (most recent call last):
...
IndexError: UnsignedInfinityRing only has one generator
>>> from sage.all import *
>>> UnsignedInfinityRing.gen()
Infinity
>>> UnsignedInfinityRing.gen(Integer(1))
Traceback (most recent call last):
...
IndexError: UnsignedInfinityRing only has one generator
UnsignedInfinityRing.gen()
UnsignedInfinityRing.gen(1)
gens()[source]

The “generator” of self is the infinity object.

EXAMPLES:

sage: UnsignedInfinityRing.gens()
(Infinity,)
>>> from sage.all import *
>>> UnsignedInfinityRing.gens()
(Infinity,)
UnsignedInfinityRing.gens()
less_than_infinity()[source]

This is the element that represents a finite value.

EXAMPLES:

sage: UnsignedInfinityRing.less_than_infinity()
A number less than infinity
sage: UnsignedInfinityRing(5) is UnsignedInfinityRing.less_than_infinity()
True
>>> from sage.all import *
>>> UnsignedInfinityRing.less_than_infinity()
A number less than infinity
>>> UnsignedInfinityRing(Integer(5)) is UnsignedInfinityRing.less_than_infinity()
True
UnsignedInfinityRing.less_than_infinity()
UnsignedInfinityRing(5) is UnsignedInfinityRing.less_than_infinity()
ngens()[source]

The unsigned infinity ring has one “generator.”

EXAMPLES:

sage: UnsignedInfinityRing.ngens()
1
sage: len(UnsignedInfinityRing.gens())
1
>>> from sage.all import *
>>> UnsignedInfinityRing.ngens()
1
>>> len(UnsignedInfinityRing.gens())
1
UnsignedInfinityRing.ngens()
len(UnsignedInfinityRing.gens())
sage.rings.infinity.is_Infinite(x)[source]

This is a type check for infinity elements.

EXAMPLES:

sage: sage.rings.infinity.is_Infinite(oo)
doctest:warning...
DeprecationWarning: The function is_Infinite is deprecated;
use 'isinstance(..., InfinityElement)' instead.
See https://github.com/sagemath/sage/issues/38022 for details.
True
sage: sage.rings.infinity.is_Infinite(-oo)
True
sage: sage.rings.infinity.is_Infinite(unsigned_infinity)
True
sage: sage.rings.infinity.is_Infinite(3)
False
sage: sage.rings.infinity.is_Infinite(RR(infinity))
False
sage: sage.rings.infinity.is_Infinite(ZZ)
False
>>> from sage.all import *
>>> sage.rings.infinity.is_Infinite(oo)
doctest:warning...
DeprecationWarning: The function is_Infinite is deprecated;
use 'isinstance(..., InfinityElement)' instead.
See https://github.com/sagemath/sage/issues/38022 for details.
True
>>> sage.rings.infinity.is_Infinite(-oo)
True
>>> sage.rings.infinity.is_Infinite(unsigned_infinity)
True
>>> sage.rings.infinity.is_Infinite(Integer(3))
False
>>> sage.rings.infinity.is_Infinite(RR(infinity))
False
>>> sage.rings.infinity.is_Infinite(ZZ)
False
sage.rings.infinity.is_Infinite(oo)
sage.rings.infinity.is_Infinite(-oo)
sage.rings.infinity.is_Infinite(unsigned_infinity)
sage.rings.infinity.is_Infinite(3)
sage.rings.infinity.is_Infinite(RR(infinity))
sage.rings.infinity.is_Infinite(ZZ)
sage.rings.infinity.test_comparison(ring)[source]

Check comparison with infinity.

INPUT:

  • ring – a sub-ring of the real numbers

OUTPUT:

Various attempts are made to generate elements of ring. An assertion is triggered if one of these elements does not compare correctly with plus/minus infinity.

EXAMPLES:

sage: from sage.rings.infinity import test_comparison
sage: rings = [ZZ, QQ, RDF]
sage: rings += [RR, RealField(200)]                                             # needs sage.rings.real_mpfr
sage: rings += [RLF, RIF]                                                       # needs sage.rings.real_interval_field
sage: for R in rings:
....:     print('testing {}'.format(R))
....:     test_comparison(R)
testing Integer Ring
testing Rational Field
testing Real Double Field...
sage: test_comparison(AA)                                                       # needs sage.rings.number_field
>>> from sage.all import *
>>> from sage.rings.infinity import test_comparison
>>> rings = [ZZ, QQ, RDF]
>>> rings += [RR, RealField(Integer(200))]                                             # needs sage.rings.real_mpfr
>>> rings += [RLF, RIF]                                                       # needs sage.rings.real_interval_field
>>> for R in rings:
...     print('testing {}'.format(R))
...     test_comparison(R)
testing Integer Ring
testing Rational Field
testing Real Double Field...
>>> test_comparison(AA)                                                       # needs sage.rings.number_field
from sage.rings.infinity import test_comparison
rings = [ZZ, QQ, RDF]
rings += [RR, RealField(200)]                                             # needs sage.rings.real_mpfr
rings += [RLF, RIF]                                                       # needs sage.rings.real_interval_field
for R in rings:
    print('testing {}'.format(R))
    test_comparison(R)
test_comparison(AA)                                                       # needs sage.rings.number_field

Comparison with number fields does not work:

sage: x = polygen(ZZ, 'x')
sage: K.<sqrt3> = NumberField(x^2 - 3)                                          # needs sage.rings.number_field
sage: (-oo < 1 + sqrt3) and (1 + sqrt3 < oo)    # known bug                     # needs sage.rings.number_field
False
>>> from sage.all import *
>>> x = polygen(ZZ, 'x')
>>> K = NumberField(x**Integer(2) - Integer(3), names=('sqrt3',)); (sqrt3,) = K._first_ngens(1)# needs sage.rings.number_field
>>> (-oo < Integer(1) + sqrt3) and (Integer(1) + sqrt3 < oo)    # known bug                     # needs sage.rings.number_field
False
x = polygen(ZZ, 'x')
K.<sqrt3> = NumberField(x^2 - 3)                                          # needs sage.rings.number_field
(-oo < 1 + sqrt3) and (1 + sqrt3 < oo)    # known bug                     # needs sage.rings.number_field

The symbolic ring handles its own infinities, but answers False (meaning: cannot decide) already for some very elementary comparisons:

sage: test_comparison(SR)               # known bug                             # needs sage.symbolic
Traceback (most recent call last):
...
AssertionError: testing -1000.0 in Symbolic Ring: id = ...
>>> from sage.all import *
>>> test_comparison(SR)               # known bug                             # needs sage.symbolic
Traceback (most recent call last):
...
AssertionError: testing -1000.0 in Symbolic Ring: id = ...
test_comparison(SR)               # known bug                             # needs sage.symbolic
sage.rings.infinity.test_signed_infinity(pos_inf)[source]

Test consistency of infinity representations.

There are different possible representations of infinity in Sage. These are all consistent with the infinity ring, that is, compare with infinity in the expected way. See also Issue #14045

INPUT:

  • pos_inf – a representation of positive infinity

OUTPUT:

An assertion error is raised if the representation is not consistent with the infinity ring.

Check that Issue #14045 is fixed:

sage: InfinityRing(float('+inf'))
+Infinity
sage: InfinityRing(float('-inf'))
-Infinity
sage: oo > float('+inf')
False
sage: oo == float('+inf')
True
>>> from sage.all import *
>>> InfinityRing(float('+inf'))
+Infinity
>>> InfinityRing(float('-inf'))
-Infinity
>>> oo > float('+inf')
False
>>> oo == float('+inf')
True
InfinityRing(float('+inf'))
InfinityRing(float('-inf'))
oo > float('+inf')
oo == float('+inf')

EXAMPLES:

sage: from sage.rings.infinity import test_signed_infinity
sage: test_signed_infinity(oo)
sage: test_signed_infinity(float('+inf'))
sage: test_signed_infinity(RLF(oo))                                             # needs sage.rings.real_interval_field
sage: test_signed_infinity(RIF(oo))                                             # needs sage.rings.real_interval_field
sage: test_signed_infinity(SR(oo))                                              # needs sage.symbolic
>>> from sage.all import *
>>> from sage.rings.infinity import test_signed_infinity
>>> test_signed_infinity(oo)
>>> test_signed_infinity(float('+inf'))
>>> test_signed_infinity(RLF(oo))                                             # needs sage.rings.real_interval_field
>>> test_signed_infinity(RIF(oo))                                             # needs sage.rings.real_interval_field
>>> test_signed_infinity(SR(oo))                                              # needs sage.symbolic
from sage.rings.infinity import test_signed_infinity
test_signed_infinity(oo)
test_signed_infinity(float('+inf'))
test_signed_infinity(RLF(oo))                                             # needs sage.rings.real_interval_field
test_signed_infinity(RIF(oo))                                             # needs sage.rings.real_interval_field
test_signed_infinity(SR(oo))                                              # needs sage.symbolic