Copyright (c) 2005 John Abbott
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the licence is included in the file COPYING in this directory.
User documentation for the files RingHom.H and RingHom.C
========================================================
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.
Constructors
------------
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], 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]), gives the
unique homomorphism from Z to R
NewPolyRingHom(Rx, S, CoeffHom, xImages)
where Rx is a [PolyRing] 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], gives the embedding homomorphism from
the coefficient ring into the polynomial ring.
EmbeddingHom(FrF)
where FrF is a [FractionField], 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], 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).
Applying a RingHom
------------------
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).
Composition
-----------
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"
Domain and Codomain
-------------------
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
Kernel
------
Currently it is not possible to ask for the kernel of a RingHom.
Member Functions for Operations on Raw Values
---------------------------------------------
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).
Maintainer documentation for the files RingHom.H and RingHom.C
==============================================================
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.
Bugs, Shortcomings and other ideas
==================================
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]
(a) S is an identical copy of R
(b) S is the same (poly)ring as R but with a different term ordering
(c) R, S are the same polynomial ring (same vars and ordering)
but with different coefficients
(d) each generator of R maps to a power product (or 0) in S
(e) S is the same as R but with more variables (is also of type (d))
(f) permutation of the variables (is also of type (d))
(g) general homomorphism mapping
(h) S is the fraction field of R