|
The following functions deal with types or category names and
general structures. Magma has two levels of granularity when referring to
types. In most cases, the coarser grained types (of type Cat) are used.
Examples of these kinds of types are "polynomial rings" (RngUPol) and
"finite fields" (FldFin). However, sometimes more specific typing
information is sometimes useful. For instance, the algorithm used to factorize
polynomials differs significantly, depending on the coefficient ring. Hence,
we might wish to implement a specialized factorization algorithm polynomials
over some particular ring type. Due to this need, Magma also supports extended types.
An extended type (of type ECat) can be thought of as a type taking a
parameter. Using extended types, we can talk about "polynomial rings over the
integers" (RngUPol[RngInt]), or "maps from the integers to the
rationals" (Map[RngInt, FldRat]). Extended types can interact with
normal types in all ways, and thus generally only need to be used when the
extra level of information is required.
Category(x) : Elt -> Cat
Given any object x, return the type (or category name) of x.
ExtendedCategory(x) : Elt -> ECat
Given any object x, return the extended type (or category name) of x.
ISA(T, U) : Cat, ECat -> BoolElt
ISA(T, U) : ECat, Cat -> BoolElt
ISA(T, U) : ECat, ECat -> BoolElt
Given types (or extended types) T and U, return whether T ISA U, i.e.,
whether objects of type T inherit properties of type U. For example, ISA(RngInt, Rng) is true, because the ring of integers Z is a ring.
Returns the underlying base type of the extended type T.
Returns the number of parametrizing objects for the extended type T.
The i-th parametrizing object of the extended type T. Although this will
usually be another extended type, as the example below shows it may not be.
We show some of the possibilities of the extended types. First we define
some simple objects and show their extended types.
> Z := Integers();
> Zx<x> := PolynomialRing(Z);
> S := [ x ];
> f1 := map<Zx -> Z | f :-> Evaluate(f, 1)>;
> D := CremonaDatabase();
>
> ExtendedType(Z);
RngInt
> ExtendedType(Zx);
RngUPol[RngInt]
> ExtendedType(S);
SeqEnum[RngUPolElt[RngInt]]
> ExtendedType(f1);
Map[RngUPol[RngInt], RngInt]
> ExtendedType(D);
DB["CrvEll"]
We can see a few points of note from the above.
If the type is not parameterized at all, like Z, then the extended
type prints as just the base type.
The printing for S shows that extended types may themselves be
further parameterized.
The printing for f1 shows that there may be more than one parametrizing
object.
The printing for D shows that parametrizing objects are not necessarily
extended types.
We can use further investigate these with the intrinsics BaseType,
'#', and indexing.
> tS := ExtendedType(S);
> BaseType(tS);
SeqEnum
> #tS;
1
> tS[1];
RngUPolElt[RngInt]
> #tS[1];
1
> tS[1][1];
RngInt
> Type(tS[1][1]);
ECat
>
> tD := ExtendedType(D);
> BaseType(tD);
DB
> #tD;
1
> tD[1];
CrvEll
> Type(tD[1]);
MonStgElt
This information could be put together to generate a tree of the type
information (represented as a list).
> function tree(t)
> if Type(t) ne ECat then
> return [* t *];
> end if;
> return [* BaseType(t) *] cat [* $$(t[i]) : i in [1..#t] *];
> end function;
> function type_tree(object)
> return tree(ExtendedType(object));
> end function;
>
> type_tree(Z);
[* RngInt *]
> type_tree(Zx);
[* RngUPol, [* RngInt *] *]
> type_tree(S);
[* SeqEnum, [* RngUPolElt, [* RngInt *] *] *]
> type_tree(f1);
[* Map, [* RngUPol, [* RngInt *] *], [* RngInt *] *]
> type_tree(D);
[* DB, [* CrvEll *] *]
Remember that the "CrvEll" in the last tree is a string, not a type.
> Type($1[2][1]);
MonStgElt
Given a string S specifying a type return the actual type
corresponding to S. This is useful when some intrinsic name hides
the symbol which normally refers to the actual type.
Given any structure S, return the type of the elements of S.
For example, the element type of the ring of integers Z is
RngIntElt since that is the type of the integers which
lie in Z.
Given structures S and T, return a covering structure C for
S and T, so that S and T both embed into C. An error
results if no such covering structure exists.
Given structures S and T, return whether a covering structure C for
S and T exists, and if so, return such a C, so that S and T
both embed into C.
We demonstrate the type and structure functions.
> Type(3);
RngIntElt
> t := MakeType("RngIntElt");
> t;
RngIntElt
> Type(3) eq t;
true
> Z := IntegerRing();
> Type(Z);
RngInt
> ElementType(Z);
RngIntElt
> ISA(RngIntElt, RngElt);
true
> ISA(RngIntElt, GrpElt);
false
> ISA(FldRat, Fld);
true
The following give examples of when covering structures exist or do not
exist.
> Q := RationalField();
> CoveringStructure(Z, Q);
Rational Field
> ExistsCoveringStructure(Z, DihedralGroup(3));
false
> ExistsCoveringStructure(Z, CyclotomicField(5));
true Cyclotomic Field of order 5 and degree 4
> ExistsCoveringStructure(CyclotomicField(3), CyclotomicField(5));
true Cyclotomic Field of order 15 and degree 8
> ExistsCoveringStructure(GF(2), GF(3));
false
> ExistsCoveringStructure(GF(2^6), GF(2, 15));
true Finite field of size 2^30
Our last example demonstrates the use of extended types:
> R<x> := PolynomialRing(Integers());
> ExtendedType(R);
RngUPol[RngInt]
> ISA(RngUPol[RngInt], RngUPol);
true
> f := x + 1;
> ExtendedType(f);
RngUPolElt[RngInt]
> ISA(RngUPolElt[RngInt], RngUPolElt);
true
[Next][Prev] [Right] [Left] [Up] [Index] [Root]
|