Skip to content

ToNumberField

Status: Stable

documented, exercised by the test suite and/or worked examples, with no known limitations recorded.

Description

ToNumberField[a, theta]

expresses the algebraic number a in the field Q(theta) as an AlgebraicNumber object, or remains unevaluated if a is not in Q(theta).

ToNumberField[{a1, a2, ...}, theta]

expresses each ai in Q(theta).

ToNumberField[{a1, a2, ...}]

expresses the ai in a common extension field generated by a single algebraic number; ToNumberField[{a1, ...}, All] uses the smallest common extension field.

ToNumberField[x]

converts any algebraic number to an explicit AlgebraicNumber object. The ai and theta may be radicals, Root objects, or AlgebraicNumber objects. Attribute: Protected.

Examples (9)

Every input below was run against the current Mathilda build and its output recorded.

Basic examples (4)

In[1]:= ToNumberField[Sqrt[2], 2^(1/4)]
Out[1]= AlgebraicNumber[Root[-2 + #1^4 &, 2], {0, 0, 1, 0}]

In[2]:= ToNumberField[2, 1/2]
Out[2]= 2

Primitive element of Q(Sqrt[2], I)

In[3]:= ToNumberField[{Sqrt[2], I}, All][[1, 1]]
Out[3]= Root[9 - 2 #1^2 + #1^4 &, 4]
In[4]:= ToNumberField[Sqrt[Sqrt[2] + Sqrt[3]]]
Out[4]= AlgebraicNumber[Root[1 - 10 #1^4 + #1^8 &, 4], {0, 1, 0, 0, 0, 0, 0, 0}]

Applications (5)

Express Sqrt[2] in Q(Sqrt[2]) itself

In[5]:= ToNumberField[Sqrt[2]]
Out[5]= AlgebraicNumber[Sqrt[2], {0, 1}]

0 + 1 Sqrt[2] in the named field

In[6]:= ToNumberField[Sqrt[2], Sqrt[2]]
Out[6]= AlgebraicNumber[Sqrt[2], {0, 1}]

Coefficients {1, 1} in Q(Sqrt[2])

In[7]:= ToNumberField[1 + Sqrt[2], Sqrt[2]]
Out[7]= AlgebraicNumber[Sqrt[2], {1, 1}]

A common field for two numbers that share one

In[8]:= ToNumberField[{Sqrt[2], Sqrt[8]}]
Out[8]= {AlgebraicNumber[3 Sqrt[2], {0, 1/3}], AlgebraicNumber[3 Sqrt[2], {0, 2/3}]}

Sqrt[3] is not in Q(Sqrt[2]): stays unevaluated

In[9]:= ToNumberField[Sqrt[3], Sqrt[2]]
Out[9]= ToNumberField[Sqrt[3], Sqrt[2]]

Implementation notes

Algorithm. builtin_tonumberfield classifies the argument forms and defers every field computation to src/poly/flint_qqbar.c; each produced AlgebraicNumber is re-canonicalised by the evaluator.

  • ToNumberField[a, theta] → flint_qqbar_to_number_field. Convert a and theta with to_qqbar, build the algebraic-integer generator phi = algint_generator(theta) of degree n, then express a as a polynomial in phi with qqbar_express_in_field_esc_all — which escalates the working precision for a named generator (fix A14), so a genuine relation that needs more than the default precision is not misread as non-membership. poly_to_algnum renders AlgebraicNumber[g, {..}] (or a rational); the result is NULL — leaving ToNumberField unevaluated — exactly when a ∉ Q(theta).
  • ToNumberField[x] → flint_qqbar_to_number_field_self, i.e. x expressed in Q(x) itself.
  • ToNumberField[{a1, …, ak}], […, Automatic], […, All] → flint_qqbar_to_number_field_common. A primitive element of the compositum is built as alpha = a1 + Σ c_i a_i, with each c chosen by degree rather than by trial membership: alpha + c·b ∈ Q(alpha, b) for every c, so the largest deg(alpha + c·b) over c ∈ 1..16 is the compositum degree (all but finitely many c give a primitive element). Choosing by degree sidesteps a membership test that could fail for want of precision — the defect that once made ToNumberField[{2^(1/6), 2^(1/3)}] (a degree-6 field resolvable only above 64 bits) come back unevaluated. Each a_i is then expressed in Q(alpha).
  • ToNumberField[{a1, …, ak}, theta] → each a_i expressed in Q(theta); declines if any a_i ∉ Q(theta).

Data structures. FLINT qqbar_t for the inputs, the primitive element and phi; fmpq_poly for the field expression; the AlgebraicNumber[theta, {coeffs}] representation for every output element. The common-field path uses a calloc'd result array so an early express-in-field miss leaves the untouched tail NULL for the error-path cleanup.

Complexity / limits. The single-generator form costs one express-in-field solve; the common-field form adds a primitive-element search (16 candidate c per adjoined generator). Bounded by the degree cap QQBAR_DEGREE_CAP = 120. Protected, and deliberately not Listable: the {a1, …} form defines one common field over the whole list, so threading element-wise would destroy its meaning.

Attributes: Protected.

References

See also: AlgebraicNumber, Root

Notes & additional examples

Notes

ToNumberField[a, theta] expresses the algebraic number a in the field Q(theta) as an AlgebraicNumber object, or stays unevaluated when a is not an element of Q(theta) — the Sqrt[3] in Q(Sqrt[2]) example. ToNumberField[x] converts a single number to an explicit AlgebraicNumber in Q(x).

ToNumberField[{a1, a2, …}] builds a single common extension field generated by one algebraic number (a primitive element of the compositum) and expresses each ai in it; ToNumberField[{a1, …}, theta] uses the named field. Because the list form defines one field over the whole list, ToNumberField is not Listable. Requires FLINT.