CoCoALib-0.9905 date: 23 May 2007

CoCoA::FractionField Class Reference

#include <FractionField.H>

Inheritance diagram for CoCoA::FractionField:

Inheritance graph
Collaboration diagram for CoCoA::FractionField:

Collaboration graph
List of all members.

Public Member Functions

 FractionField (const FractionFieldBase *RingPtr)
const FractionFieldBaseoperator-> () const
 allow const member fns to be called
const RingBasemyRawPtr () const
 Used by "downcasting" functions IsRingFp, AsRingFp, etc.

Private Member Functions

FractionFieldoperator= (const FractionField &rhs)
 NEVER DEFINED -- disable assignment.

Detailed Description

      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 FractionField

A FractionField in the CoCoA Library is a fraction field of an effective
GCD domain.  A FractionField offers all the operations of a ring plus a
few new specific operations.

To create a new FractionField from a GCDDomain use NewFractionField:

  FractionField QR = NewFractionField(R);

This creates a new object of type FractionField whose elements are
formal fractions of elements of R.  CoCoA::FractionField is derived from
CoCoA::ring, so a FractionField is a ring.

Given a FractionField the function BaseRing tells us which ring it is
the FractionField of:

  R == BaseRing(QR); // yields true

BaseRing(QR) produces an identical copy of R (not merely an isomorphic ring).

Given just a plain ring S we can enquire whether S is in fact a
FractionField, and if so "view" it as such:
  if (IsFractionField(S))
     FractionField FrF = AsFractionField(S);
     ... code using FrF ...

Calling AsFractionField(S) when IsFractionField(S) is false will throw an
exception of type CoCoAError with code ERR::NotFracField

Let r be a RingElem belonging to a FractionField QR.  Then
  num(r)  -- gives a copy of the numerator of r as an element of BaseRing(QR)
  den(r)  -- gives a copy of the denominator of r as an element of BaseRing(QR)

Note that the numerator and denominator are defined only upto multiples
by a unit: so it is possible to have two elements of QR which are equal
but which have different numerators and denominators, for instance,
 (x-1)/(x-2)  =  (1-x)/(2-x)

Maintainer documentation for FractionField, FractionFieldBase, FractionFieldImpl

The class FractionField is wholly analogous to the class ring, i.e. a
reference counting smart pointer.  The only difference is that
FractionField knows that the myRingPtr data member actually points to an
instance of a class derived from FractionFieldBase (and so can safely
apply a static_cast when the pointer value is accessed).

FractionFieldBase is an abstract class derived from RingBase.  It adds a
few pure virtual functions to those contained in RingBase:

    virtual const ring& BaseRing() const = 0;
    virtual void num(RawValue& n, ConstRawValue q) const = 0; // n is elem of BaseRing!!
    virtual void den(RawValue& d, ConstRawValue q) const = 0; // d is elem of BaseRing!!
    virtual const RingHom& EmbeddingHom() const = 0;
    virtual RingHom NewInducedHom(const RingHom&) const = 0;

BaseRing returns a reference to the ring (effective GCD domain) supplied
to the constructor.

num (resp. den) produces a copy of the numerator (resp. denominator) of q:
NOTE that the first arg belongs to BaseRing and NOT to the FractionField!
EmbeddingHom returns the embedding homomorphism from the BaseRing into
the FractionField; it actually returns a reference to a fixed
homomorpism held internallly.
InducedHom creates a new homomorpism from the FractionField to another
ring S given a homomorpism from the BaseRing to S.

FractionFieldImpl implements a general fraction field.  Its
elements are just pairs of RawValues belonging to the BaseRing (see the
struct FractionFieldElem).  For this implementation the emphasis
was clearly on simplicity over speed (at least partly because we do not
expect FractionFieldImpl to be used much).  For polynomials whose
coefficients lie in a FractionField we plan to implement a specific ring
which uses a common denominator representation for the whole polynomial.
If you want to make this code faster, see some of the comments in the
bugs section.

Important: while fractions are guaranteed to be reduced (i.e. no common
factor exists between numerator and denominator), it is rather hard to
ensure that they are "canonical" since in general we can multiply numerator
and denominator by any unit.  See a "bug" comment about normalizing units.

Bugs, Shortcomings and other ideas

The functions myNew are not "exception safe": memory would be leaked if
space for the numerator were successfully allocated while allocation for
the denominator failed -- nobody would clean up the resources consumed
by the numerator.  Probably need a sort of auto_ptr for holding
temporary bits of a value.

I don't like the names myGetNum and myGetDen.  Hope to change them soon.

Should partial homomorphisms be allowed: e.g. from Q to Z/(3)?
Mathematically it is a bit dodgy, but in practice all works
out fine provided you don't divide by zero.  I think it would be too
useful (e.g. for chinese remaindering methods) to be banned.
Given phi:Z->Z[x]  it might be risky to induce Q->Z[x];
note that ker(phi)=0, so this is not a sufficient criterion!

In fact one could create a FractionFieldImpl of any integral domain
(it just wouldn't be possible to cancel factors without a GCD).  I'll
wait until someone really needs it before allowing it.

It is not clear how to make the denominator positive when the GCD domain
is Z (so the fraction field is Q).  In general we would need the GCD domain
to supply a "normalizing unit": such a function could return 1 unless we
have some special desire to normalize the denominator in a particular way.
HERE'S A CONUNDRUM: FractionField(Q[x]) -- all rationals are units, and
so we could end up with horrible representations like (22/7)/(22/7)
instead of just 1.  MUST FIX THIS!!

The printing function is TERRIBLE!

FASTER + and -
  Addition and subtraction can be done better:
  let h be the GCD of the two denominators,
  suppose we want to compute  a/bh + c/dh
  (where gcd(a,bh) = gcd(c, dh) = gcd(b,d) = 1
   i.e. h = gcd(B,D) where B,D are the denoms)
  If h = 1 then there is no cancellation,
  o/w gcd(ad+bc, bdh) = gcd(ad+bc, h), so we can use a simpler
  gcd computation to find the common factor.

FASTER * and /
  Multiplication and division can also be made a little faster by simplifying
  the GCD computation a bit.  The two cases are essentially the same, so I
  shall consider just multiplication.  Assuming inputs are already reduced
  (i.e. there is no common factor between numerator and denominator).
  To compute (a/b)*(c/d), first calculate h1 = gcd(a, d) and h2 = gcd(b, c).
  The result is then: num = (a/h1)*(c/h2)  &  den = (b/h2)*(d/h1)
  and this is guaranteed to be in reduced form.

[myIsRational] is incomplete: it will fail to recognise rationals whose
numer and denom have been multiplied by non-trivial units.  BAD BUG!
Ironically [myIsInteger] does work correctly.

Definition at line 48 of file FractionField.H.

Constructor & Destructor Documentation

CoCoA::FractionField::FractionField const FractionFieldBase RingPtr  )  [explicit]

Member Function Documentation

FractionField& CoCoA::FractionField::operator= const FractionField rhs  )  [private]

NEVER DEFINED -- disable assignment.

const FractionFieldBase * CoCoA::FractionField::operator->  )  const [inline]

allow const member fns to be called

Reimplemented from CoCoA::ring.

Definition at line 79 of file FractionField.H.

References CoCoA::ring::operator->().

const RingBase* CoCoA::ring::myRawPtr  )  const [inline, inherited]

Used by "downcasting" functions IsRingFp, AsRingFp, etc.

Definition at line 61 of file ring.H.

References CoCoA::SmartPtrIRC< T >::myRawPtr(), and CoCoA::ring::mySmartPtr.

Referenced by CoCoA::AsPolyRing(), CoCoA::AsSparsePolyRing(), CoCoA::IsPolyRing(), CoCoA::IsSparsePolyRing(), and CoCoA::operator==().

The documentation for this class was generated from the following file:
Generated on Wed May 23 13:44:25 2007 for CoCoALib by  doxygen 1.4.6