Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

algebraeon

Algebraeon support for Koto: arbitrary precision arithmetic, number theory, polynomials, and matrices.

The module provides the types N (natural numbers), Z (integers), Q (rationals), Poly (univariate polynomials), Mat (matrices), Quat (Hamilton quaternions) and Alg (real algebraic numbers), plus the module-level functions gcd and lcm.

Naming convention

Basic number domains use ASCII forms of their mathematical symbols: N (naturals), Z (integers), and Q (rationals). Zn(n) is the residue ring ℤ/nℤ. Other structures use PascalCase names or established acronyms, for example Poly, Mat, ComplexAlg, FF, and CF.

The former constructors NN, ZZ, and ZZn remain compatibility aliases during the 0.2 transition. They construct the same canonical N, Z, and Zn runtime types.

N

|| -> Iterator
|Number| -> N

Natural (non-negative integer) values with arbitrary precision.

Called with no arguments, N() returns an iterator over the natural numbers 0, 1, 2, ....

Example

print! N(5).factorial()
check! 120

print! N(5) - N(3)
check! 2

print! N().take(4).to_list()
check! [0, 1, 2, 3]

N.bitcount

|N| -> Number

Returns the number of bits needed to represent the value.

Example

print! N(5).bitcount()
check! 3

N.is_prime

|N| -> Bool

Returns true if the value is prime.

Example

print! N(17).is_prime()
check! true

print! N(12).is_prime()
check! false

N.is_squarefree

|N| -> Bool

Returns true if the value has no repeated prime factors.

Example

print! N(10).is_squarefree()
check! true

print! N(12).is_squarefree()
check! false

N.factor

|N| -> [(N, N)]

Returns the prime factorization of the value as a list of (prime, exponent) tuples.

Example

print! N(60).factor()
check! [(2, 2), (3, 1), (5, 1)]

N.factorial

|N| -> N

Returns the factorial of the value.

Example

print! N(5).factorial()
check! 120

N.divisors

|N| -> [N]

Returns the value’s divisors in ascending order.

Example

print! N(12).divisors()
check! [1, 2, 3, 4, 6, 12]

N.euler_totient

|N| -> N

Returns the value of Euler’s totient function, the count of positive integers up to the value that are coprime to it.

Example

print! N(10).euler_totient()
check! 4

N.is_square

|N| -> Bool

Returns true if the value is a perfect square.

Example

print! N(16).is_square()
check! true

print! N(18).is_square()
check! false

N.sqrt_floor

|N| -> N

Returns the floor of the square root of the value.

Example

print! N(17).sqrt_floor()
check! 4

N.sqrt_ceil

|N| -> N

Returns the ceiling of the square root of the value.

Example

print! N(17).sqrt_ceil()
check! 5

N.is_power_test

|N| -> (Bool, N?, N?)

Returns (true, base, exponent) if the value can be written as base^exponent with exponent > 1, otherwise (false, null, null).

Example

print! N(8).is_power_test()
check! (true, 2, 3)

print! N(6).is_power_test()
check! (false, null, null)

N.primality_test

|N| -> String

Returns 'prime' or 'composite' (both 0 and 1 are reported as 'composite').

Example

print! N(17).primality_test()
check! prime

print! N(12).primality_test()
check! composite

N.primes

|| -> Iterator

Returns an iterator over the prime numbers.

Example

print! N.primes().take(6).to_list()
check! [2, 3, 5, 7, 11, 13]

Z

|Number| -> Z

Integer values with arbitrary precision.

Z supports arithmetic (+ - *), comparisons, and assignment operators (+= -= *=) with other Z values, N values, and plain numbers.

Example

print! Z(5) + Z(-3)
check! 2

print! Z(4) * Z(-2)
check! -8

print! Z(5) + N(3)
check! 8

Z.abs

|Z| -> N

Returns the absolute value of the integer as an N.

Example

print! Z(-9).abs()
check! 9

Z.is_irreducible

|Z| -> Bool

Returns true if the value is irreducible (i.e. a prime, up to sign).

Example

print! Z(7).is_irreducible()
check! true

print! Z(9).is_irreducible()
check! false

Z.is_square

|Z| -> Bool

Returns true if the value is a perfect square.

Example

print! Z(9).is_square()
check! true

print! Z(10).is_square()
check! false

Z.factor

|Z| -> [(Z, N)]

Returns the prime factorization of the value as a list of (prime, exponent) tuples. The sign is ignored.

Example

print! Z(-12).factor()
check! [(2, 2), (3, 1)]

Z.divmod

|Z, Z| -> (Z, Z)

Returns the quotient and remainder of a floor division, with a non-negative remainder.

Example

print! Z(-7).divmod(Z(3))
check! (-3, 2)

Z.div_floor

|Z, Z| -> Z

Returns the quotient of a floor division.

Example

print! Z(-7).div_floor(Z(3))
check! -3

print! Z(-13).div_floor(Z(5))
check! -3

Z.mod

|Z, Z| -> Z

Returns the non-negative remainder of a floor division, coherent with div_floor.

Example

print! Z(-7).mod(Z(3))
check! 2

print! Z(-13).mod(Z(5))
check! 2

Q

|Number| -> Q
|Number, Number| -> Q

Rational numbers, stored as reduced fractions num / den.

The denominator must be non-zero. A single argument is treated as a whole number. Q supports arithmetic (+ - * /), comparisons, and assignment operators (+= -= *= /=) with other Q values, N values, Z values and plain numbers.

The display form is the reduced fraction num/den, or just num when the denominator is 1.

Example

print! Q(6, 4)
check! 3/2

print! Q(1, 2) + Q(1, 3)
check! 5/6

print! Q(1, 2) / Q(3, 4)
check! 2/3

print! Q(0.5)
check! 1/2

print! Q(3)
check! 3

Q.num

|Q| -> Z

Returns the numerator of the reduced fraction.

Example

print! Q(3, 2).num()
check! 3

print! Q(-3, 2).num()
check! -3

Q.den

|Q| -> N

Returns the denominator of the reduced fraction.

Example

print! Q(3, 2).den()
check! 2

Q.is_integer

|Q| -> Bool

Returns true if the value is a whole number.

Example

print! Q(4, 2).is_integer()
check! true

print! Q(3, 2).is_integer()
check! false

Q.is_square

|Q| -> Bool

Returns true if the value is a perfect square.

Example

print! Q(4, 9).is_square()
check! true

print! Q(2, 3).is_square()
check! false

Q.sqrt_if_square

|Q| -> Q?

Returns the square root of the value if it is a perfect square, otherwise null.

Example

print! Q(4, 9).sqrt_if_square()
check! 2/3

print! Q(2, 3).sqrt_if_square()
check! null

Q.height

|Q| -> N

Returns the height of the value: max(|num|, den) of the reduced fraction.

Example

print! Q(3, 2).height()
check! 3

print! Q(-2, 5).height()
check! 5

Q.to_float

|Q| -> Number

Converts the value to a floating point number.

Example

print! Q(3, 2).to_float()
check! 1.5

Q.to_zz

|Q| -> Z

Converts the value to a Z (the value must be a whole number).

Example

print! Q(3).to_zz()
check! 3

print! Q(4, 2).to_zz()
check! 2

Q.to_nn

|Q| -> N

Converts the value to an N (the value must be a non-negative whole number).

Example

print! Q(4, 2).to_nn()
check! 2

print! Q(0).to_nn()
check! 0

Poly

|List| -> Poly

Univariate polynomials over Z or Q.

The constructor takes a list of coefficients in ascending order, with the first element being the constant term: Poly([6, -5, 1]) represents 6 - 5x + x^2.

The coefficients are stored as Z when all of them are integers, and promoted to Q when any of them is a fraction. Arithmetic (+ - *) works with other polynomials and with N/Z/Q scalars, promoting Z to Q when needed.

The display form shows the terms in ascending order of degree, e.g. 6 - 5x + x^2.

Example

a = Poly([6, -5, 1])
print! a
check! 6 - 5x + x^2

print! a + Poly([1, 1])
check! 7 - 4x + x^2

print! a * Q(1, 2)
check! 3 - (5/2)x + (1/2)x^2

Poly.degree

|Poly| -> N

Returns the degree of the polynomial (the zero polynomial has degree 0).

Example

print! Poly([6, -5, 1]).degree()
check! 2

print! Poly([7]).degree()
check! 0

Poly.coeffs

|Poly| -> [Z] | [Q]

Returns the coefficients in ascending order, starting with the constant term.

Example

print! Poly([6, -5, 1]).coeffs()
check! [6, -5, 1]

print! Poly([3, Q(-5, 2), Q(1, 2)]).coeffs()
check! [3, -5/2, 1/2]

Poly.eval

|Poly, x: Number| -> Z | Q

Evaluates the polynomial at x (which may be a Number, N, Z or Q).

Example

a = Poly([6, -5, 1])
print! a.eval(2)
check! 0

print! a.eval(Q(1, 2))
check! 15/4

Poly.derivative

|Poly| -> Poly

Returns the derivative of the polynomial.

Example

print! Poly([6, -5, 1]).derivative()
check! -5 + 2x

print! Poly([5]).derivative()
check! 0

Poly.gcd

|Poly, Poly| -> Poly

Returns the monic greatest common divisor of two polynomials, promoting to Q if needed.

Example

print! Poly([6, -5, 1]).gcd(Poly([2, -3, 1]))
check! -2 + x

Poly.factor

|Poly| -> [(Poly, N)]

Returns the irreducible factorization of the polynomial as a list of (factor, exponent) tuples.

Example

print! Poly([6, -5, 1]).factor()
check! [(-2 + x, 1), (-3 + x, 1)]

print! Poly([1, 0, 1]).factor()
check! [(1 + x^2, 1)]

Mat

|List of lists| -> Mat

Matrices over Z or Q, given row by row: Mat([[1, 2], [3, 4]]) is the 2x2 matrix with rows [1, 2] and [3, 4].

The entries are stored as Z when all of them are integers, and promoted to Q when any of them is a fraction. Arithmetic (+ - *) works with other matrices and with N/Z/Q scalars.

The display form is a list of rows, e.g. [[1, 2], [3, 4]].

Example

m = Mat([[1, 2], [3, 4]])
print! m
check! [[1, 2], [3, 4]]

print! m * Mat([[5, 6], [7, 8]])
check! [[19, 22], [43, 50]]

print! m.det()
check! -2

Mat.rows

|Mat| -> N

Returns the number of rows.

Example

print! Mat([[1, 2], [3, 4]]).rows()
check! 2

Mat.cols

|Mat| -> N

Returns the number of columns.

Example

print! Mat([[1, 2], [3, 4]]).cols()
check! 2

Mat.at

|Mat, row: Number, col: Number| -> Z | Q

Returns the entry at the given row and column (zero-based).

Example

print! Mat([[1, 2], [3, 4]]).at(1, 0)
check! 3

Mat.transpose

|Mat| -> Mat

Returns the transposed matrix.

Example

print! Mat([[1, 2], [3, 4]]).transpose()
check! [[1, 3], [2, 4]]

Mat.mul

|Mat, Mat| -> Mat

Returns the matrix product (also available as the * operator).

Example

m = Mat([[1, 2], [3, 4]])
print! m.mul(Mat([[5, 6], [7, 8]]))
check! [[19, 22], [43, 50]]

Mat.det

|Mat| -> Z | Q

Returns the determinant (only defined for square matrices).

Example

print! Mat([[1, 2], [3, 4]]).det()
check! -2

Mat.inverse

|Mat| -> Mat

Returns the inverse of the matrix over Q (a Z matrix is promoted to Q). An error is thrown if the matrix is singular.

Example

m = Mat([[1, 2], [3, 4]])
print! m.inverse()
check! [[-2, 1], [3/2, -1/2]]

print! m.inverse() * m
check! [[1, 0], [0, 1]]

Mat.lll

|Mat| -> Mat

Returns the LLL-reduced basis of the lattice generated by the rows of an integer matrix. An error is thrown if the matrix contains fractions.

Example

print! Mat([[1, 1], [1, 2]]).lll()
check! [[-1, 0], [0, 1]]

gcd

|N, N| -> N

Returns the greatest common divisor of two natural numbers.

Example

print! gcd(N(12), N(18))
check! 6

lcm

|N, N| -> N

Returns the least common multiple of two natural numbers.

Example

print! lcm(N(4), N(6))
check! 12

Quat

|Number, Number, Number, Number| -> Quat

Hamilton quaternions over Q, constructed from four coefficients a + bi + cj + dk (each Number/N/Z/Q argument is promoted to Q).

Multiplication is the Hamilton product, defined by i^2 = j^2 = k^2 = ijk = -1 with i*j = k, j*k = i and k*i = j (the cross terms anti-commute: j*i = -k, …), so multiplication is not commutative. The product is computed directly on the coefficients: the wrapper works around a bug in algebraeon 0.0.17 (upstream issue #244) that produced wrong signs in the i/j cross terms of QuaternionAlgebraStructure::mul.

Quat supports arithmetic (+ - *) with other Quat values and with scalars (Number/N/Z/Q, on either side), negation, and equality (==, !=).

The display form is e.g. 1 + 2i - 3j + (1/2)k: zero terms are omitted, the coefficient 1 is dropped on i/j/k, and fractional coefficients are parenthesized.

Example

q = Quat(1, 2, 3, 4)
print! q
check! 1 + 2i + 3j + 4k

print! q + Quat(1, -2, -3, -4)
check! 2

print! q * 2
check! 2 + 4i + 6j + 8k

print! 1 - q
check! -2i - 3j - 4k

print! Quat(1, 2, 0, 0) * Quat(3, 4, 0, 0)
check! -5 + 10i

# Hamilton rules: i*j = k, j*i = -k, i*i = -1
i = Quat(0, 1, 0, 0)
j = Quat(0, 0, 1, 0)
k = Quat(0, 0, 0, 1)
print! i * j
check! k

print! j * i
check! -k

print! i * i
check! -1

# Associativity: (i*j)*k = -1
print! (i * j) * k
check! -1

Quat.conjugate

|Quat| -> Quat

Returns the conjugate a - bi - cj - dk.

Example

print! Quat(1, 2, 3, 4).conjugate()
check! 1 - 2i - 3j - 4k

print! Quat(1, 2, 3, 4).conjugate().conjugate()
check! 1 + 2i + 3j + 4k

Quat.norm

|Quat| -> Q

Returns the reduced norm a^2 + b^2 + c^2 + d^2.

Example

print! Quat(1, 2, 3, 4).norm()
check! 30

print! Quat(3, -4, 0, 0).norm()
check! 25

Quat.trace

|Quat| -> Q

Returns the reduced trace 2a.

Example

print! Quat(1, 2, 3, 4).trace()
check! 2

print! Quat(3, -4, 0, 0).trace()
check! 6

Quat.coeffs

|Quat| -> (Q, Q, Q, Q)

Returns the four coefficients as a tuple (a, b, c, d).

Example

print! Quat(1, 2, 3, 4).coeffs()
check! (1, 2, 3, 4)

print! Quat(Q(1, 2), 0, 0, 0).coeffs()
check! (1/2, 0, 0, 0)

Quat.to_float

|Quat| -> (Number, Number, Number, Number)

Converts the four coefficients to floating point numbers.

Example

print! Quat(1, 2, 3, 4).to_float()
check! (1.0, 2.0, 3.0, 4.0)

Alg

|Poly | List| -> [Alg]

Real algebraic numbers: exact real roots of polynomials. The constructor takes a Poly (over Z or Q) or a coefficient list (as in Poly([...])), and returns the list of isolated real roots in increasing order, with multiplicity. Polynomials of degree 0 (including the zero polynomial) and polynomials without real roots give an empty list.

Each Alg value is a root with an isolating interval, so comparisons are exact: <, <=, >, >= and == work between two Alg values and between an Alg and a scalar (Q/N/Z/Number, compared exactly as a rational). Arithmetic between algebraic numbers is not exposed.

The display form is a decimal approximation with 9 significant decimals (e.g. 1.414213562), or the exact reduced fraction for rational values (e.g. 6).

Example

roots = Alg(Poly([-2, 0, 1]))  # roots of x^2 - 2
print! roots
check! [-1.414213562, 1.414213562]

print! size(roots)
check! 2

print! roots[0] < roots[1]
check! true

print! Alg(Poly([1, -2, 1]))  # (x - 1)^2, multiplicity kept
check! [1, 1]

print! Alg(Poly([1, 0, 1]))  # x^2 + 1 has no real roots
check! []

print! Alg([-2, 0, 1])  # coefficient list form
check! [-1.414213562, 1.414213562]

Alg.cmp

|Alg, Alg | Number| -> Number

Exact comparison: -1 if smaller, 0 if equal, 1 if greater. The argument may be another Alg or a scalar (Number/N/Z/Q), compared exactly as a rational.

Example

roots = Alg(Poly([-2, 0, 1]))
print! roots[0].cmp(roots[1])
check! -1

sqrt2 = roots[1]
print! sqrt2.cmp(Q(141, 100))  # sqrt(2) > 141/100
check! 1

Alg.accuracy

|Alg| -> Q

Returns the width of the isolating interval (an exact rational). Rational values have accuracy 0.

Example

print! Alg(Poly([-2, 0, 1]))[0].accuracy() > Q(0)
check! true

print! Alg(Poly([-6, 1]))[0].accuracy()  # rational root
check! 0

Alg.refine

|Alg, accuracy: Q | Number| -> Alg

Returns a new Alg whose isolating interval has been refined to the requested (positive) accuracy. Rational values are returned unchanged.

Example

sqrt2 = Alg(Poly([-2, 0, 1]))[1]
r = sqrt2.refine(Q(1, 1000))
print! r.accuracy() < Q(1, 1000)
check! true

print! r.cmp(sqrt2)
check! 0

Alg.min_poly

|Alg| -> Poly

Returns the minimal polynomial of the algebraic number (a Poly over Q). For a rational value n/d it is d*x - n.

Example

sqrt2 = Alg(Poly([-2, 0, 1]))[1]
print! sqrt2.min_poly()
check! -2 + x^2

print! Alg(Poly([-6, 1]))[0].min_poly()
check! -6 + x

Alg.to_float

|Alg| -> Number

Returns a floating point approximation; the isolating interval is refined to accuracy 10^-15 before converting the midpoint.

Example

sqrt2 = Alg(Poly([-2, 0, 1]))[1]
print! sqrt2.to_float()
check! 1.4142135623730951

print! Alg(Poly([-6, 1]))[0].to_float()
check! 6.0

Ideal

|Number, ...| -> Ideal

Ideals of Z are principal. Ideal(a, b, ...) is the ideal generated by its integer arguments; its canonical non-negative generator is displayed with suffix Z. Thus Ideal(4, 6) is 2Z.

Example

print! Ideal(4, 6)
check! 2Z

print! Ideal(6).generator()
check! 6

print! Ideal(6).contains(12)
check! true

print! Ideal(6).contains(5)
check! false

Ideal.contains

|Ideal, Number| -> Bool

Tests whether an integer belongs to the ideal. N and Z values are also accepted.

Example

print! Ideal(6).contains(Z(-12))
check! true

print! Ideal(0).contains(3)
check! false

Ideal.generator

|Ideal| -> N

Returns the canonical non-negative generator.

Example

print! Ideal(-4, 6).generator()
check! 2

Ideal.sum

|Ideal, Ideal| -> Ideal

Returns the sum of two ideals. In Z, this is the ideal generated by the greatest common divisor of their generators.

Example

print! Ideal(6).sum(Ideal(15))
check! 3Z

Ideal.intersect

|Ideal, Ideal| -> Ideal

Returns the intersection of two ideals. In Z, its generator is the least common multiple of the two generators.

Example

print! Ideal(6).intersect(Ideal(15))
check! 30Z

Ideal.product

|Ideal, Ideal| -> Ideal

Returns the product of two ideals.

Example

print! Ideal(6).product(Ideal(15))
check! 90Z

Ideal.quotient

|Ideal, Ideal| -> Ideal

Returns the ideal quotient (I : J) = {x in Z : xJ subset I}.

Example

print! Ideal(6).quotient(Ideal(2))
check! 3Z

Ideal.equals

|Ideal, Ideal| -> Bool

Tests equality of ideals by comparing their canonical generators. The == operator can be used as well.

Example

print! Ideal(4, 6).equals(Ideal(2))
check! true

print! Ideal(6) == Ideal(-6)
check! true

Zn

|Number| -> Zn

The ring Zn(n) is ℤ/nℤ, the ring of integers modulo a positive modulus n. Call .of(x) to create the residue class of an integer. Classes from the same ring support +, -, * and unary -; their display is [x] mod n with a canonical representative.

Example

print! Zn(6)
check! Zn

print! Zn(6).of(7) + Zn(6).of(5)
check! [0] mod 6

print! -Zn(6).of(1)
check! [5] mod 6

Zn.of

|Zn, Number| -> ZnElement

Creates a residue class, reducing the argument modulo the ring modulus. N and Z values are accepted too.

Example

print! Zn(7).of(-1)
check! [6] mod 7

print! Zn(6).of(7) * Zn(6).of(5)
check! [5] mod 6

ZnElement.inverse

|ZnElement| -> ZnElement

Returns a multiplicative inverse. It errors when the residue is not coprime to the modulus.

Example

print! Zn(7).of(5).inverse()
check! [3] mod 7

FF

|Number| -> FF
|Number, Number| -> FF

Finite fields are written GF(p) or GF(p^k), where p is prime. FF(p) constructs the prime field, while FF(p, k) constructs the extension field using the Conway polynomial from Algebraeon’s database. Elements are made with .of(x).

Example

print! FF(7)
check! GF(7)

print! FF(7).char(), FF(7).degree()
check! (7, 1)

print! FF(2, 2)
check! GF(2^2)

FF.of

|FF, Number| -> FFElement
|FF, List| -> FFElement

For GF(p), .of(x) reduces an integer modulo p. For GF(p^k), a list contains coefficients in ascending degree order, [c0, c1, ...], and is reduced modulo the Conway polynomial.

Example

print! FF(7).of(-1)
check! 6

x = FF(2, 2).of([0, 1])
print! x * x
check! x + 1

print! x.coeffs()
check! [0, 1]

FFElement.inverse

|FFElement| -> FFElement

Returns the multiplicative inverse of a non-zero finite-field element.

Example

print! FF(7).of(3).inverse()
check! 5

FFElement.order

|FFElement| -> N

Returns the multiplicative order of a non-zero element.

Example

print! FF(7).of(3).order()
check! 6

FFElement.pow

|FFElement, Number| -> FFElement

Raises an element to an integer power. Negative powers use the multiplicative inverse.

Example

print! FF(7).of(2).pow(-1)
check! 4

print! FF(2, 2).of([0, 1]).pow(3)
check! 1

CF

|List| -> CF

A simple continued fraction. CF([a0, a1, ...]) is finite and coefficients after the first must be positive. Its display uses [a0, a1, ...].

Example

print! CF([3, 7])
check! [3, 7]

print! CF([3, 7]).value()
check! 22/7

print! CF([3, 7]).convergent(1)
check! 22/7

CF.periodic

|List, List| -> CF

Constructs an infinite periodic continued fraction from its initial and repeating parts. For example, [1; 2, 2, ...] represents the continued fraction expansion of the square root of 2.

Example

s2 = CF.periodic([1], [2])
print! s2
check! [1; 2]

print! s2.convergent(3)
check! 17/12

CF.value

|CF| -> Q

Returns the exact rational value of a finite continued fraction. It is not defined for periodic or infinite continued fractions.

Example

print! CF([3, 7]).value()
check! 22/7

CF.convergent

|CF, N| -> Q

Returns the convergent at index n, starting at index zero. Convergents also work for periodic and infinite continued fractions.

Example

print! CF.periodic([1], [2]).convergent(4)
check! 41/29

CF.take

|CF, N| -> [Z]

Returns the first n coefficients as a list of Z values. A finite continued fraction stops when its coefficients run out.

Example

print! CF([3, 7]).take(4)
check! [3, 7]

CF.to_float

|CF| -> Number

Returns a floating-point approximation. Finite fractions are evaluated exactly before conversion; infinite fractions use a convergent.

Example

print! CF([3, 7]).to_float()
check! 3.142857142857143

Perm

|List| -> Perm

A permutation is given by its list of images, indexed from zero. For example, Perm([1, 2, 0]) maps 0 -> 1, 1 -> 2 and 2 -> 0. Composition p * q applies q first and then p.

Example

p = Perm([1, 2, 0])
q = Perm([0, 2, 1])
print! p
check! [1, 2, 0]

print! p * q
check! [1, 0]

print! p.inverse()
check! [2, 0, 1]

Perm.compose

|Perm, Perm| -> Perm

Composes two permutations with the same convention as *: the argument is applied first.

Example

print! Perm([1, 2, 0]).compose(Perm([0, 2, 1]))
check! [1, 0]

Perm.inverse

|Perm| -> Perm

Returns the inverse permutation.

Example

p = Perm([1, 2, 0])
print! p.compose(p.inverse())
check! []

Perm.sign

|Perm| -> Number

Returns 1 for an even permutation and -1 for an odd permutation.

Example

print! Perm([0, 2, 1]).sign()
check! -1

print! Perm([1, 2, 0]).sign()
check! 1

Perm.cycles

|Perm| -> [[Number]]

Returns the disjoint cycles. Fixed points are omitted.

Example

print! Perm([2, 0, 1, 4, 3]).cycles()
check! [[0, 2, 1], [3, 4]]

Perm.cycle_shape

|Perm| -> [Number]

Returns the sorted lengths of the non-trivial disjoint cycles.

Example

print! Perm([2, 0, 1, 4, 3]).cycle_shape()
check! [2, 3]

Perm.call

|Perm, Number| -> Number

Returns the image of an index under the permutation.

Example

p = Perm([1, 2, 0])
print! p.call(2)
check! 0

Perm.all

|Number| -> [Perm]

Returns all permutations in S_n.

Example

print! size(Perm.all(3))
check! 6

Group

|| -> Group

Group provides finite groups represented by multiplication tables. The constructors are cyclic(n), dihedral(n), symmetric(n), alternating(n), klein4(), quaternion() and trivial().

Example

print! Group.cyclic(4)
check! C4 (size 4)

print! Group.symmetric(3)
check! S3 (size 6)

Group.size

|Group| -> Number

Returns the number of elements in the group.

Example

print! Group.dihedral(3).size()
check! 6

Group.order

|Group, Number| -> Number

Returns the order of the element at the given table index. The identity is index 0.

Example

print! Group.cyclic(4).order(1)
check! 4

print! Group.cyclic(4).order(2)
check! 2

Group.is_abelian

|Group| -> Bool

Returns whether the group operation is commutative.

Example

print! Group.cyclic(4).is_abelian()
check! true

print! Group.dihedral(3).is_abelian()
check! false

Group.conjugacy_classes

|Group| -> [[Number]]

Returns the conjugacy classes as sorted lists of element indices.

Example

print! Group.dihedral(3).conjugacy_classes()
check! [[0], [1, 2, 4], [3, 5]]

ComplexAlg

|Poly | List| -> [ComplexAlg]
|Number| -> ComplexAlg
|Number, Number| -> ComplexAlg

Complex algebraic numbers are exact roots of polynomials. With a Poly or a coefficient list, ComplexAlg(...) returns all complex roots with multiplicity. With one scalar it constructs a rational real value; with two scalars ComplexAlg(a, b) constructs a + b*i. The imaginary unit is ComplexAlg.i().

Example

i = ComplexAlg.i()
print! i
check! i

print! i * i
check! -1

print! size(ComplexAlg(Poly([1, 0, 1])))
check! 2

ComplexAlg.real

|ComplexAlg| -> Alg

Returns the exact real part as an Alg value.

Example

print! ComplexAlg(Q(1), Q(2)).real()
check! 1

ComplexAlg.imag

|ComplexAlg| -> Alg

Returns the exact imaginary part as an Alg value.

Example

print! ComplexAlg(Q(1), Q(2)).imag()
check! 2

ComplexAlg.conjugate

|ComplexAlg| -> ComplexAlg

Returns the complex conjugate.

Example

print! ComplexAlg(Q(1), Q(2)).conjugate()
check! 1 - 2i

ComplexAlg.min_poly

|ComplexAlg| -> Poly

Returns the minimal polynomial over Q.

Example

print! ComplexAlg(Q(1), Q(2)).min_poly()
check! 5 - 2x + x^2

ComplexAlg.degree

|ComplexAlg| -> N

Returns the degree of the minimal polynomial.

Example

print! ComplexAlg.i().degree()
check! 2

ComplexAlg.to_float

|ComplexAlg| -> [Number, Number]

Returns a floating-point approximation as [real, imag].

Example

print! ComplexAlg(Q(1), Q(2)).to_float()
check! [1.0, 2.0]

legendre

|Number, Number| -> Z

Returns the Legendre symbol (a / p) as -1, 0 or 1. The bottom argument must be an odd prime.

Example

print! legendre(2, 7)
check! 1

print! legendre(3, 7)
check! -1

jacobi

|Number, Number| -> Z

Returns the Jacobi symbol (a / n) for an odd positive n; n need not be prime.

Example

print! jacobi(2, 9)
check! 1

print! jacobi(3, 9)
check! 0

kronecker

|Number, Number| -> Z

Returns the Kronecker symbol (a / n), extending the Jacobi symbol to even, negative and zero bottom arguments.

Example

print! kronecker(2, 8)
check! 0

print! kronecker(3, 8)
check! -1

eulers_constant

|| -> CF

Returns the infinite continued fraction for Euler’s number e: [2; 1, 2, 1, 1, 4, ...].

Example

e_cf = eulers_constant()
print! e_cf.take(9)
check! [2, 1, 2, 1, 1, 4, 1, 1, 6]

print! e_cf.convergent(5)
check! 87/32

Z.ideal

|Z| -> Ideal

Returns the principal ideal generated by the integer. The generator is canonicalized, so negative integers produce the same ideal as their absolute values.

Example

print! Z(-6).ideal()
check! 6Z

print! Z(0).ideal()
check! 0Z