The class RingHom
is intended to represent homomorphisms between rings.
Currently there is no way to represent more general maps between rings.
It is possible to create a "partial homomorphism" which can generate
run-time errors when applied to certain values.
A RingHom
is a "constant object": its value is determined at the moment
of its creation, and cannot be changed. There is no default constructor,
and assignment of RingHom
s is not allowed.
Here is a complete list of pseudo-constructors for ring homomorphisms
(some are defined in other files, e.g. QuotientRing.H
or FractionField.H
).
NewIdentityRingHom(R) where R may be any ring, gives the identity homomorphism on R NewInducedHom(RmodI, phi) where RmodI is a [``QuotientRing`` QuotientRing.html], gives the homomorphism induced by phi (which must have the base ring of RmodI as its domain, and whose kernel must contain the defining ideal of RmodI) NewZEmbeddingHom(Z, R) where Z is the ring of integers (i.e. a [``RingZ`` RingZ.html]), gives the unique homomorphism from Z to R NewPolyRingHom(Rx, S, CoeffHom, xImages) where Rx is a [``PolyRing`` PolyRing.html] and CoeffHom is a homomorphism whose domain is the coefficient ring of Rx and xImages is a ``vector`` of ``RingElem`` specifying the images of the indeterminates, gives the homomorphism from Rx to S mapping coefficients according to CoeffHom and mapping the k-th indeterminate of Rx to the k-th value in xImages (i.e. having index k-1) CoeffEmbeddingHom(P) where P is a [``PolyRing`` PolyRing.html], gives the embedding homomorphism from the coefficient ring into the polynomial ring. EmbeddingHom(FrF) where FrF is a [``FractionField`` FractionField.html], gives the embedding homomorphism from the base ring into the fracion field (i.e. x |-> x/1) NewInducedHom(FrF, phi) where FrF is a [``FractionField`` FractionField.html], gives the homomorphism induced by phi (which must have the base ring of FrF as its domain). Note that the resulting homomorphism may be only partial (e.g. if ker(phi) is non-trivial, or if the codomain is not a field).
A RingHom
may applied using natural syntax:
- let phi be an object of type RingHom
- let x be an object of type RingElem
- let n be of type long
or int
- let N be an object of type ZZ
-
phi(x) applies phi to x; error if owner(x) != domain(phi) phi(n) applies phi to n phi(N) applies phi to N
In all cases the result is a RingElem
belonging to the codomain of
phi. Currently "partial" homomorphisms are allowed, so applying a
RingHom could trigger an error (e.g. an induced hom from Q to Z/(3)
applied to 1/3).
Two RingHom
s may be composed using a fairly natural syntax: if we have
two RingHom
s phi:R -> S and theta:S -> T then their composition may
be computed using the syntax
theta(phi) the composite homomorphism "apply phi first then theta"
We may ask for the domain and codomain of a RingHom
phi:
domain(phi) gives a const ref to the domain codomain(phi) gives a const ref to the codomain
Note that the domain and codomain are merely ring
s, they "forget"
any special ring type
Currently it is not possible to ask for the kernel of a RingHom.
All operations on a RingHom
are invisibly converted into member function
calls on a RingHomBase
. It is possible to call these member functions
directly: the main difference is that the member functions do not perform
any sanity checking on their arguments (so they should be slightly faster
but if you hand in incompatible arguments, you'll probably get an ugly
crash).
These files contain two "generic" classes (RingHom
and RingHomBase
), and
a trivial concrete class representing the identity ring homomorphism,
IdentityRingHom
. Most of this section is dedicated to the two generic
classes since they represent the primary contribution to the CoCoA
library.
The class RingHom
is little more than a "reference counting smart
pointer" class to objects of type RingHomBase
; this latter type is
designed to support intrusive reference counting. Beyond its role as a
smart pointer RingHom
offers four "function application" syntaxes:
RingElem RingHom::operator()(ConstRefRingElem x) const; RingElem RingHom::operator()(long n) const; RingElem RingHom::operator()(const ZZ& N) const; RingHom RingHom::operator()(const RingHom&) const;
The first three support a natural syntax for applying the homomorphism to a ring element, a small integer, or a large integer. The last offers a fairly natural syntax for creating the composition of two homomorphisms.
The class RingHomBase
is a purely abstract class which is used to specify
the interface which any concrete ring homomorphism class must offer. In
particular this base class already includes an intrusive reference counter,
as required by RingHom
. It also includes two private data members
myDomainValue
and myCodomainValue
which store the domain and codomain
rings. Note that these data fields are plain ring
s and so "forget" any
special ring type which the domain or codomain may have had. Originally I
had hoped to preserve any special ring type information, but this seemed to
lead to a confusing and complex implementation (which probably would never
have worked as I hoped). The two ring
fields may be read using the accessor
fnuctions:
const ring& myDomain() const; const ring& myCodomain() const;
A concrete class implementing a ring homomorphism must supply definition for the following (pure virtual) functions:
virtual void myApply(RingBase::RawValue& image, RingBase::ConstRawValue arg) const; virtual void myOutputSelf(std::ostream& out) const;
DO NOTE THAT the two arguments to myApply
normally belong to
DIFFERENT rings. arg
belongs to myDomain()
whereas image
belongs to myCodomain()
. The function myOutputSelf
should
print out a useful description of the homomorphism.
First version of the documentation ==> rather spartan.
Cannot compute a kernel of a RingHom.
Arranging for domain(phi) and codomain(phi) to preserve C++ type
information about the respective rings (e.g. PolyRing
or FractionField
rather than simply ring
), appears to be difficult to achieve in any
reasonable manner. I've decided that it is much simpler just to discard
all special type information, and return simply ring
s. If the user knows
something more, he can use a "cast" function like AsFractionField
. Even
if it were feasible to maintain such C++ type info, there would have to
n-squared cases to cover all possible combinations of domain and codomain.
We should implement more special cases: e.g. same vars different coeff ring, PP --> PP, other... Also need some way of handling canonical homomorphisms.
Some special cases of homomorphic embeddings R --> S: (may belong with the special types of ring to which they are associated)