© 2005,2007,2012 John Abbott, Anna M. Bigatti
GNU Free Documentation License, Version 1.2

CoCoALib Documentation Index

User documentation for RingZZ

The call RingZZ() produces the CoCoA ring which represents ZZ, the ring of integers. Calling RingZZ() several times will always produce the same unique CoCoA ring representing ZZ.

Strictly, there is a limit on the size of elements you can create, but the limit is typically high enough not to be bothersome.

See RingElem for operations on its elements.

Efficiency of arithmetic on elements of RingZZ() should be reasonable rather than spectacular. If you wish to compute purely with integers (without exploiting CoCoALib's rings) then see the documentation in BigInt.


Constructors and pseudo-constructors


Let R be a ring


Let S be a ring

Maintainer documentation for the class RingZZImpl

The function RingZZ() simply returns the unique instance of the CoCoALib ring representing ZZ. This instance is managed by GlobalManager, see its documentation.

The function MakeUniqueInstanceOfRingZZ is the only function which can call the ctor of RingZZImpl. The only function which is supposed to call MakeUniqueInstanceOfRingZZ is the ctor of GlobalManager. I have discouraged others from calling MakeUniqueInstanceOfRingZZ by not putting it in the header file RingZZ.H -- see bugs section in GlobalManager.

The class RingZZImpl is really very simple. It may look daunting and complex because it inherits lots of virtual functions from RingBase. It contains just three data members: a MemPool for managing the storage of the mpz_t headers, and pointers to the ring's own zero and one elements.

The member functions for arithmetic are all quite simple. The only minor difficulty is in the function AsMPZ which gets at the mpz_t hidden inside a RingElemRawPtr. I have decided to stick with the C interface to GMP for the moment (even though GMP 4 does offer a C++ interface). This appears to be more a personal choice than a technical one.

Recall (from ring) that arithmetic on ring elements always passes via the virtual member functions of the concrete rings, and that these expect arguments to be of type RawPtr or ConstRawPtr. The arguments are pointers to the mpz_t headers which reside in a region of memory controlled by the MemPool belonging to the RingZZImpl class.

Given that the mpz_t values must live on the free store, we use a MemPool to handle the space for their headers (which are of fixed size). Note that this MemPool is NOT what handles the memory used for the digits (or limbs) of the GMP integer values! Currently limb space is handled by whatever is the default allocator (malloc, I suppose).

The data members myZeroPtr and myOnePtr just hold auto_ptrs to the zero and one elements of the RingZZImpl. I used an auto_ptr to avoid having to worry about freeing it in the destructor; the zero and one values cannot be RingElems because their creation must be deferred. I opted not to store the values in RingElem fields to avoid any possible problem due to a "race condition" where elements of the ring would be constructed before the body of the constructor of the ring had begun execution (might be OK anyway, but could easily lead to hair-raising bugs (e.g. in the dtor)).

Bugs, Shortcomings and other ideas

This code is probably not exception safe; I do not know what the mpz_* functions do when there is insufficient memory to proceed. Making the code "exception safe" could well be non-trivial: I suspect a sort of auto_ptr to an mpz_t value might be needed.

Should I switch to the C++ interface for GMP integers?

It is a shame that the mpz_t headers are "out of line". How much this may affect run-time performance I don't know.

Generation of random elements in RingZZ is not possible (yet???).