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[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
0 + 1 Sqrt[2] in the named field
Coefficients {1, 1} in Q(Sqrt[2])
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
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. Convertaandthetawithto_qqbar, build the algebraic-integer generatorphi = algint_generator(theta)of degreen, then expressaas a polynomial inphiwithqqbar_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_algnumrendersAlgebraicNumber[g, {..}](or a rational); the result isNULL— leavingToNumberFieldunevaluated — exactly whena ∉ Q(theta).ToNumberField[x]→flint_qqbar_to_number_field_self, i.e.xexpressed inQ(x)itself.ToNumberField[{a1, …, ak}],[…, Automatic],[…, All]→flint_qqbar_to_number_field_common. A primitive element of the compositum is built asalpha = a1 + Σ c_i a_i, with eachcchosen by degree rather than by trial membership:alpha + c·b ∈ Q(alpha, b)for everyc, so the largestdeg(alpha + c·b)overc ∈ 1..16is the compositum degree (all but finitely manycgive a primitive element). Choosing by degree sidesteps a membership test that could fail for want of precision — the defect that once madeToNumberField[{2^(1/6), 2^(1/3)}](a degree-6 field resolvable only above 64 bits) come back unevaluated. Eacha_iis then expressed inQ(alpha).ToNumberField[{a1, …, ak}, theta]→ eacha_iexpressed inQ(theta); declines if anya_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
- H. Cohen, A Course in Computational Algebraic Number Theory, GTM 138 (Springer, 1993), §4.2 (power-basis representation) and the primitive-element theorem for a compositum.
- The FLINT library (https://flintlib.org),
qqbarmodule — field membership (qqbar_express_in_field) and primitive-element construction. - Source:
src/poly/tonumberfield.c - Specification:
docs/spec/builtins/algebra.md - Tests:
tests/test_algebraicnumber.c - Tests:
tests/test_algebraicnumberdenominator.c - Tests:
tests/test_algebraicnumbernorm.c - Tests:
tests/test_algebraicnumbertrace.c
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.