|typedef double ||value_t|
Public Member Functions
| ||SmallFpDoubleImpl (unsigned long p)|
| ||SmallFpDoubleImpl (const ZZ &P)|
|void ||myAssignZero (value_t &lhs) const |
| ||lhs = 0 |
|void ||myAssign (value_t &lhs, value_t x) const |
| ||lhs = x |
|void ||myAssign (value_t &lhs, long n) const |
| ||lhs = n |
|void ||myAssign (value_t &lhs, const ZZ &N) const |
| ||lhs = N |
|void ||myNegate (value_t &lhs, value_t x) const |
| ||lhs = -x |
|void ||myAdd (value_t &lhs, value_t x, value_t y) const |
| ||lhs = x+y |
|void ||mySub (value_t &lhs, value_t x, value_t y) const |
| ||lhs = x-y |
|void ||myMul (value_t &lhs, value_t x, value_t y) const |
| ||lhs = x*y |
|void ||myDiv (value_t &lhs, value_t x, value_t y) const |
| ||lhs = x/y |
|bool ||myIsDivisible (value_t &lhs, value_t x, value_t y) const |
| ||lhs = x/y, if y is non-zero |
|void ||myPower (value_t &lhs, value_t x, unsigned long n) const |
| ||lhs = x^n |
|void ||myOutput (std::ostream &out, value_t x) const |
| ||out << x |
|void ||myOutput (OpenMathOutput &OMOut, value_t x) const |
| ||OMOut << x. |
|bool ||myIsPrintAtom (value_t x) const |
|bool ||myIsPrintedWithMinus (value_t x) const |
|bool ||myIsZero (value_t x) const |
| ||x == 0 |
|bool ||myIsOne (value_t x) const |
| ||x == 1 |
|bool ||myIsMinusOne (value_t x) const |
| ||x == -1 |
|bool ||myIsInteger (ZZ &N, value_t x) const |
| ||copy value of x into n, result is always true |
|bool ||myIsZeroAddMul (value_t &lhs, value_t y, value_t z) const |
|bool ||myIsEqual (value_t x, value_t y) const |
Static Public Attributes
|static const std::size_t ||DatumSize = sizeof(value_t)|
Private Member Functions
| ||SmallFpDoubleImpl (const SmallFpDoubleImpl &)|
|SmallFpDoubleImpl & ||operator= (const SmallFpDoubleImpl &)|
|value_t ||myReduceMod (value_t n) const |
Static Private Member Functions
|static value_t ||CheckCtorArg (unsigned long p)|
|static value_t ||CheckCtorArg (const ZZ &P)|
|static value_t ||CalcDrop (value_t p)|
|static value_t ||CalcIterLimit (value_t p)|
|static value_t ||MaxInt ()|
|const value_t ||myModulus|
|const value_t ||myDrop|
|const value_t ||myIterLimit|
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 SmallFpDoubleImpl
The class [SmallFpDoubleImpl] is NOT INTENDED for use by "casual" CoCoALib
users. If you wish to compute in finite fields see the documentation in
QuotientRing.txt (in particular the function [NewZmod]), or possibly the
documentation in RingFp.txt, RingFpLog.txt, and RingFpDouble.txt.
Compared to [SmallFpImpl] the main difference is an implementation
detail: values are represnted as [double]s -- on 32-bit computers this
allows a potentially usefully greater range of characteristics at a
probably minor run-time cost.
A [SmallFpDoubleImpl] object cannot be used as a CoCoA ring, even though the
implementation is rather reminiscent of a ring implementation class.
ALL OPERATIONS on values must be effected by calling member functions
of the [SmallFpDoubleImpl] class. Here is a brief summary.
SmallFpImpl::value_t a, b, c;
ModP.myAdd(a, b, c);
ModP.mySub(a, b, c);
ModP.myMul(a, b, c);
ModP.myDiv(a, b, c);
where inv(c) is inverse of c
Maintainer documentation for SmallFpDoubleImpl
Most functions are implemented inline, and no sanity checks are
performed (except when CoCoA_DEBUG is enabled). The constructor
does do some checking. The basic idea is to use the extra precision
available in [double]s to allow larger prime finite fields than are
permitted when 32-bit integers are used for all arithmetic. If fast
64-bit arithmetic becomes widespread then this class will probably
become obsolete (unless you have a very fast floating point coprocessor?).
[SmallFpDoubleImpl::value_t] is simply [double]. Note that the values
are always non-negative integers with maximum value less than
[myModulus]; i.e. each residue class is represented by its least
non-negative member. The printed form reflects this choice of
To avoid problems with "overflow" the constructor checks that all
integers from 0 to p*p+p can be represented exactly. We need to allow
numbers as big as p*p+p so that [myIsZeroAddMul] can be implemented easily.
It is not strictly necessary that [myModulus] be prime, though division
becomes only a partial map if [myModulus] is composite. I believe it is
safest to insist that [myModulus] be prime -- the function [myIsDivisible]
does indeed assume that [myModulus] is prime.
Bugs, Shortcomings, and other ideas
BUG: The use of [IsSmallPrime] in the ctor prevents use of primes
whose square is too large for an [unsigned long]. Need a specific
function which allows larger primes (on 32-bit machines).
BUG: the function [myIsInteger] assumes that any valid residue is
small enough to fit into a [long]. Strictly C++ does not guarantee
The implementation is simplistic -- I wanted to dash it off quickly
before going on holiday :-)
Precalculating a reciprocal would probably allow faster reduction modulo
[myModulus] in [myReduceMod], [myMul] and [myIsZeroAddMul].
Values are printed out as least non-negative residues. Perhaps the user
should be allowed to choose symmetric residues instead?
Should there be a function for accessing the value of myModulus?
If so, what should the type of the result be?