      QuotientRing
      Copyright (c)  2005,2012 John Abbott, Anna M. Bigatti
      GNU Free Documentation License, Version 1.2
%!includeconf: ../aux-txt2tags/config.t2t
      TeXTitle{QuotientRing}{John Abbott, Anna M. Bigatti}



== User documentation for QuotientRing ==
%======================================================================

A ``QuotientRing`` is an abstract class (inheriting from [[ring]])
representing quotients of a [[ring]] by an [[ideal]].

See [[RingElem QuotientRing]] for operations on its elements.


=== Examples ===
%----------------------------------------------------------------------
- [ex-RingFp1.C ../../examples/index.html#ex-RingFp1.C]
- [ex-RingFp2.C ../../examples/index.html#ex-RingFp2.C]


Extended example of use:
```
  RingZZ ZZ = RingZZ();           // a copy of the ring of integers
  ring ZZmod10 = NewZZmod(10);    // represents ZZ/(10) integers modulo 10
  ring ZZmod10a = NewQuotientRing(ZZ, ideal(ZZ, 10)); // same as ZZmod10

  RingHom phi = QuotientingHom(ZZmod10); // ring hom from ZZ to ZZmod10
  RingElem r(ZZmod10, -3);               // an element of ZZmod10
  RingElem preimage = CanonRepr(r);      // an element of ZZ = BaseRing(ZZmod10)

  ring S = NewZZmod(2);              // another ring S, details do not matter much
  RingHom theta = QuotientingHom(S); // any ring hom from ZZ to S will do instead
  RingHom theta_bar = NewInducedHom(ZZmod10, theta); // induced ring hom from ZZmod10 to S

  ring RmodI = NewQuotientRing(NewPolyRing(S,"x,y,z"), "x^2-2, y^3-1");
```

=== Constructors and Pseudo-constructors ===[constructors]
%----------------------------------------------------------------------
- ``NewQuotientRing(R, I)`` -- creates a new [[ring]] representing the
quotient ``R``/``I``.  ``I`` must be an ideal of ``R``; odd things may
happen if ``I``=``R``.  If ``I`` is zero then the result is isomorphic
to ``R`` but not equal to ``R``; arithmetic in ``R`` is more efficient
than arithmetic in ``R``/ideal(0).
- ``NewQuotientRing(R, str)`` -- creates a new [[ring]] representing the
quotient ``R``/``I``, where ``I`` is the ideal in ``R`` generated by the
list of [[RingElem]] in the string ``str``.
- ``NewZZmod(n)`` -- creates a new [[ring]] representing the quotient
``ZZ``/ideal(``n``) where ``ZZ`` is the ring of integers [[RingZZ]] and
``n`` is an integer.  A CoCoALib error will be thrown if ``n``=1 or
``n``=-1.  Currently an error will be thrown also if ``n``=0 (see
BUGS).
- ``QuotientRing`` -- sort of downcast the ring ``R`` to a quotient ring;
will throw an ``ErrorInfo`` object with code ``ERR::NotQuotRing`` if needed.
-


==== NewZZmod or NewRingFp? ====

If ``n`` is a small prime then ``NewZZmod(n)`` produces the same result as
``NewRingFp(n)`` (or perhaps ``NewRingFpDouble(n)``).  If ``n`` is not a
small prime then ``NewRingFp(n)`` throws an exception whereas ``NewZZmod(n)``
will produce a working quotient ring.


=== Query and cast ===[query]
%----------------------------------------------------------------------
- ``IsQuotientRing(R)`` returns true iff R is implemented as a ``QuotientRing``
- ``QuotientRingPtr(R)`` returns a pointer to the quotient ring impl (for calling mem fns);
will throw an ``ErrorInfo`` object with code ``ERR::NotQuotRing`` if needed.


=== Operations on QuotientRing ===[operations]
%----------------------------------------------------------------------
In addition to the standard [[ring operations]], a ``QuotientRing``
may be used in other functions.

Given ``RmodI`` a ``QuotientRing`` (representing R/I)
built as ``NewQuotientRing(R,I)`` 
with ``I`` is an [[ideal]] of the [[ring]] ``R``.

- ``BaseRing(RmodI)`` -- a reference to the base ring of ``RmodI``, namely ``R``
- ``DefiningIdeal(RmodI)`` -- a reference to the ideal ``I`` used to create ``RmodI``
- ``ReprRing(RmodI)`` -- a reference to the ring used for internal representation
of elements of ``RmodI``
-

=== Homomorphisms ===[homomorphisms]
%----------------------------------------------------------------------

- ``QuotientingHom(RmodI)`` -- a reference to the quotienting
homomorphism from ``R`` to ``RmodI``
- ``InducedHom(RmodI, phi)`` -- where ``phi`` is a [[RingHom]] from
``R`` to ``S``, creates a new [[RingHom]] from ``RmodI`` to ``S``.
Two types of error may occur:
  - ``ERR::BadInducingHom`` --  if ``domain(phi)`` is not ``BaseRing(RmodI)``
  - ``ERR::BadInducingHomKer`` -- if ``phi`` does not map the gens of ``I``
   to zero.
  -
-

== Maintainer documentation for QuotientRing, QuotientRingBase, GeneralQuotientRingImpl ==
%======================================================================

While considering the design of this code it may help to keep in mind
these two canonical implementations:
:  ``GeneralQuotientRingImpl``
    internally elements are represented as elements of a
    "representation ring" (which may differ from the base ring) which
    are kept reduced modulo some ideal (which may differ from the
    defining ideal)

:  ``RingFpImpl``
   internally elements are represented by machine integers (see doc
   for RingFpImpl), a representation incompatible with that used for
   elements of the ring of integers (which is probably the base ring)


``QuotientRingBase``
  is an abstract class derived from RingBase, and is the
base class for all quotient rings.  It adds the following four new pure
virtual member functions which must be defined in every concrete
quotient ring:
```
    virtual RingElem myCanonRepr(ConstRawValue r) const;
    virtual void myReduction(RawValue& image, ConstRawValue arg) const;
    virtual const RingHom& myQuotientingHom() const;
    virtual RingHom myInducedHomCtor(const RingHom& InducingHom) const;
```

The member function myCanonRepr has to return a copy of the value since
we cannot be sure that the internal representation is compatible with
the internal representation of elements of the base ring.


== Bugs, Shortcomings and other ideas ==
%======================================================================

``IamTrueGCDDomain`` always returns false.  We can be clever in some easy
cases, but it is hard in general (think of rings of algebraic integers
which are gcd domains, but not euclidean domains).

Should NewZZmod(n) allow the case n==0?  There's no mathematical
reason to forbid it, but forbidding it may help detect programmer
errors more quickly -- it seems unlikely that one would really want
to quotient by ideal(0).

FAIRLY SERIOUS CONFUSION:  the code seems to make REPEATED sanity checks see
```
  QuotientRingBase::QuotientRingBase
  NewQuotientRing

  QuotientRingHomBase::QuotientRingHomBase
  NewInducedHom
```
I suspect that the C++ ctors should use CoCoA_ASSERT instead of checking
always (and throwing an exception).


FURTHER SERIOUS CONFUSION: there is ambiguity about the difference
between myBaseRing and myReprRing esp. for creating induced
homomorphisms: given ring R, and ring S = R/I, create ring T = S/J
An induced hom from T should start from a hom with domain S;
or is it reasonable to accept a hom with domain R?  In this case
for T myReprRing is R but myBaseRing is S.


Given a RingHom from a QuotientRing it is not generally possible to
obtain a reference to an "inducing hom": consider the hom from
ZZ/(2) to ZZ/(2)[x] created by CoeffEmbeddingHom.  A RingHom equivalent
to the inducing hom can be produced by composing QuotientingHom with
the given hom.


20 March 2004: I have added the possibility of making a trivial ring by
quotienting: previously this was disallowed for no good reason that I
could discern.

