1 #ifndef CoCoA_SmallFpDoubleImpl_H
2 #define CoCoA_SmallFpDoubleImpl_H
3 
4 //   Copyright (c)  2005,2009,2011-2013  John Abbott
5 
6 //   This file is part of the source of CoCoALib, the CoCoA Library.
7 
8 //   CoCoALib is free software: you can redistribute it and/or modify
9 //   it under the terms of the GNU General Public License as published by
10 //   the Free Software Foundation, either version 3 of the License, or
11 //   (at your option) any later version.
12 
13 //   CoCoALib is distributed in the hope that it will be useful,
14 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //   GNU General Public License for more details.
17 
18 //   You should have received a copy of the GNU General Public License
19 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
20 
21 
22 // Header file for the class SmallFpDoubleImpl
23 
24 
25 #include "CoCoA/assert.H"
26 #include "CoCoA/GlobalManager.H"
27 
28 #include <cmath>
29 //using std::floor;
30 //using std::fmod;
31 
32 
33 namespace CoCoA
34 {
35 
36   class MachineInt;     // fwd decl -- defined in MachineInt.H
37   class BigInt;         // fwd decl -- defined in BigInt.H
38   class BigRat;         // fwd decl -- defined in BigRat.H
39   class SmallPrime;     // fwd decl -- defined in NumTheory-prime.H
40 
41   /*-----------------------------------------------------------------*/
42   /** \include SmallFpDoubleImpl.txt  */
43   /*-----------------------------------------------------------------*/
44   class SmallFpDoubleImpl
45   {
46   public:
47     explicit SmallFpDoubleImpl(const MachineInt& n, GlobalSettings::ResidueSetting ResidueChoice = DefaultResidueSetting());
48     explicit SmallFpDoubleImpl(SmallPrime p, GlobalSettings::ResidueSetting ResidueChoice = DefaultResidueSetting());
49     static bool IsGoodCtorArg(const MachineInt& n);
50     static bool IsGoodCtorArg(SmallPrime p);
51     static long ourMaxModulus();
52   private:
53     SmallFpDoubleImpl(const SmallFpDoubleImpl&);            // NEVER DEFINED -- copy ctor disabled
54     SmallFpDoubleImpl& operator=(const SmallFpDoubleImpl&); // NEVER DEFINED -- assignment disabled
55 
56   public:
57     typedef double value_t;
58     static const int ourDatumSize = sizeof(value_t);
59 
60     long myModulus() const;
61     value_t myReduce(const MachineInt& n) const;  ///< n % myModulus
62     value_t myReduce(const BigInt& N) const;      ///< N % myModulus
63     value_t myReduce(const BigRat& q) const;      ///< q % myModulus (error if den(q)%myModulus == 0)
64     long myExport(value_t x) const;               ///< exports x into a long (according to myResiduesAreSymm)
65 
66     value_t myNegate(value_t x) const;
67     value_t myAdd(value_t x, value_t y) const;
68     value_t mySub(value_t x, value_t y) const;
69     value_t myMul(value_t x, value_t y) const;
70     value_t myDiv(value_t x, value_t y) const;
71     value_t myPower(value_t x, long n) const;
72 
73     bool myIsZeroAddMul(value_t& lhs, value_t y, value_t z) const;///< lhs += y*z, result says whether lhs == 0.
74     value_t myNormalize(value_t n) const;
75     value_t myHalfNormalize(value_t n) const;
myMaxIters()76     long myMaxIters() const { return myIterLimit; }
77 
78   private: // Data members
79     const value_t myModulusValue;
80     const bool myResiduesAreSymm;  // Used only in myExport
81     const value_t myResidueUPBValue;
82     const long myIterLimit;
83 
84   private: // impl details
85     static value_t ourCheckCtorArg(const MachineInt& n);
86     static value_t ourCheckCtorArg(SmallPrime p);
87     static value_t ourCalcResidueUPB(value_t p);
88     static long ourCalcIterLimit(value_t p);
89     static value_t ourMaxInt();
90   };  // end of class SmallFpDoubleImpl
91 
92 
93   std::ostream& operator<<(std::ostream& out, const SmallFpDoubleImpl& arith);
94   bool operator==(const SmallFpDoubleImpl& arith1, const SmallFpDoubleImpl& arith2);
95   bool operator!=(const SmallFpDoubleImpl& arith1, const SmallFpDoubleImpl& arith2);
96 
97 
98   //------------------------------------------------------------
99   // SmallFpDoubleImpl inline functions
100   //------------------------------------------------------------
101 
myModulus()102   inline long SmallFpDoubleImpl::myModulus() const
103   {
104     return static_cast<long>(myModulusValue); // cast is safe, cannot overflow.
105   }
106 
107 
myExport(value_t x)108   inline long SmallFpDoubleImpl::myExport(value_t x) const
109   {
110     CoCoA_ASSERT(0 <= x && x < myModulusValue && x == std::floor(x));
111     if (!myResiduesAreSymm || x <= myModulusValue/2.0)
112       return static_cast<long>(x); // cast cannot overflow
113     return static_cast<long>(x - myModulusValue); // cast cannot overflow
114   }
115 
116 
myNormalize(value_t n)117   inline SmallFpDoubleImpl::value_t SmallFpDoubleImpl::myNormalize(value_t n) const
118   {
119     CoCoA_ASSERT(n >= 0 && n == std::floor(n));
120     return std::fmod(n,myModulusValue);
121   }
122 
123 
myNegate(value_t x)124   inline SmallFpDoubleImpl::value_t SmallFpDoubleImpl::myNegate(value_t x) const
125   {
126     CoCoA_ASSERT(0 <= x && x < myModulusValue && x == std::floor(x));
127     if (x == 0) return x;
128     return myModulusValue - x;
129   }
130 
131 
myAdd(value_t x,value_t y)132   inline SmallFpDoubleImpl::value_t SmallFpDoubleImpl::myAdd(value_t x, value_t y) const
133   {
134     CoCoA_ASSERT(0 <= x && x < myModulusValue && x == std::floor(x));
135     CoCoA_ASSERT(0 <= y && y < myModulusValue && y == std::floor(y));
136     const value_t ans = x+y;
137     if (ans < myModulusValue) return ans;
138     return ans - myModulusValue;
139   }
140 
141 
mySub(value_t x,value_t y)142   inline SmallFpDoubleImpl::value_t SmallFpDoubleImpl::mySub(value_t x, value_t y) const
143   {
144     CoCoA_ASSERT(0 <= x && x < myModulusValue && x == std::floor(x));
145     CoCoA_ASSERT(0 <= y && y < myModulusValue && y == std::floor(y));
146     if (x >= y) return x-y;
147     return x + (myModulusValue-y);  // avoid trying to create a negative value
148   }
149 
150 
myMul(value_t x,value_t y)151   inline SmallFpDoubleImpl::value_t SmallFpDoubleImpl::myMul(value_t x, value_t y) const
152   {
153     CoCoA_ASSERT(0 <= x && x < myModulusValue && x == std::floor(x));
154     CoCoA_ASSERT(0 <= y && y < myModulusValue && y == std::floor(y));
155     return std::fmod(x*y, myModulusValue);
156   }
157 
158 
myIsZeroAddMul(value_t & lhs,value_t x,value_t y)159   inline bool SmallFpDoubleImpl::myIsZeroAddMul(value_t& lhs, value_t x, value_t y) const
160   {
161     CoCoA_ASSERT(0 <= x && x < myModulusValue && x == std::floor(x));
162     CoCoA_ASSERT(0 <= y && y < myModulusValue && y == std::floor(y));
163     lhs = fmod(lhs+x*y, myModulusValue);
164     CoCoA_ASSERT(0 <= lhs && lhs < myModulusValue && lhs == std::floor(lhs));
165     return (lhs == 0);
166   }
167 
168 
myHalfNormalize(value_t n)169   inline SmallFpDoubleImpl::value_t SmallFpDoubleImpl::myHalfNormalize(value_t n) const
170   {
171     CoCoA_ASSERT(0 <= n && n < 2*myResidueUPBValue && n == std::floor(n));
172 //    if (n < myResidueUPBValue) return n;
173 //    return n-myResidueUPBValue;
174     if (n >= myResidueUPBValue) return n-myResidueUPBValue;
175     return n;
176   }
177 
178 
179   inline bool operator==(const SmallFpDoubleImpl& arith1, const SmallFpDoubleImpl& arith2)
180   {
181     return (arith1.myModulus() == arith2.myModulus());
182   }
183 
184   inline bool operator!=(const SmallFpDoubleImpl& arith1, const SmallFpDoubleImpl& arith2)
185   {
186     return !(arith1 == arith2);
187   }
188 
189 } // end of namespace CoCoA
190 
191 
192 // RCS header/log in the next few lines
193 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/include/CoCoA/SmallFpDoubleImpl.H,v 1.21 2020/01/26 14:17:54 abbott Exp $
194 // $Log: SmallFpDoubleImpl.H,v $
195 // Revision 1.21  2020/01/26 14:17:54  abbott
196 // Summary: Changed include of MachineInt into fwd decl
197 //
198 // Revision 1.20  2018/06/25 12:28:20  abbott
199 // Summary: Ctors now accept SmallPrime args (and skip primality tests)
200 //
201 // Revision 1.19  2014/06/17 10:03:15  abbott
202 // Summary: Changed type of myIterLimit (double -> long); makes more sense.
203 // Author: JAA
204 //
205 // Revision 1.18  2013/05/27 13:10:14  abbott
206 // Correct param type from long to MachineInt.
207 //
208 // Revision 1.17  2013/03/25 17:04:19  abbott
209 // Major clean-up of interface to SmallFpImpl/SmallFpLogImpl/SmallFpDoubleImpl
210 // (underlying impl remains much the same).  Removed lots of cruft.
211 // Consequential changes to RingFp* classes; small change to SparsePolyRing.
212 //
213 // Revision 1.16  2012/09/07 15:21:13  abbott
214 // First stage of revision of SmallFpImpl interface (and SmallFpLog, SmallFpDouble).
215 //
216 // Revision 1.15  2012/01/30 11:01:11  abbott
217 // Added naive printing fn (just to help during debugging).
218 //
219 // Revision 1.14  2011/11/09 13:50:01  bigatti
220 // -- renamed MachineInteger --> MachineInt
221 //
222 // Revision 1.13  2011/08/24 10:21:09  bigatti
223 // -- renamed QQ --> BigRat
224 //
225 // Revision 1.12  2011/08/17 11:56:12  abbott
226 // Added two static_casts to keep compiler quiet.
227 //
228 // Revision 1.11  2011/08/14 15:52:17  abbott
229 // Changed ZZ into BigInt (phase 1: just the library sources).
230 //
231 // Revision 1.10  2011/05/20 19:26:05  abbott
232 // Updated SmallFp*Impl: removed all output-related fns (must use myExport instead).
233 //
234 // Revision 1.9  2011/05/20 09:44:20  abbott
235 // Removed some no-longer-useful bits of code.
236 //
237 // Revision 1.8  2011/05/19 14:38:27  abbott
238 // Updated small prime finite field impls to allow user to specify
239 // separately for each whether to use symmetric or non-negative
240 // residues for export operations (myExport and printing).
241 //
242 // Revision 1.7  2011/03/22 20:06:13  abbott
243 // Added static mem fn IsGoodCtorArg (called by RingFp pseudo-ctors).
244 // Commented out ctors which take ZZ arg -- seems useless.
245 //
246 // Revision 1.6  2011/03/16 15:30:55  abbott
247 // Changed arg type from MachineInt into const MachineInt&.
248 //
249 // Revision 1.5  2011/03/14 10:28:15  abbott
250 // Changed unsigned long into long (and unsigned short into short).
251 //
252 // Revision 1.4  2009/05/14 09:39:29  abbott
253 // Added possibility to specify "symmetric" or "non-negative" residues
254 // in quotients of ZZ.  Affects printing of elements in quotients of ZZ
255 // (also changed printing of elements in general quotient rings).
256 // Consequent changes in several tests.
257 //
258 // Revision 1.3  2008/12/17 12:11:52  abbott
259 // Changed type from long to MachineInt in operations which use a machine integer
260 // in place of a RingElem.  The change is "superficial" but affects many files.
261 //
262 // Revision 1.2  2007/10/30 17:14:11  abbott
263 // Changed licence from GPL-2 only to GPL-3 or later.
264 // New version for such an important change.
265 //
266 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
267 // Imported files
268 //
269 // Revision 1.7  2007/03/08 18:42:05  cocoa
270 // Cleaned up whitespace.
271 //
272 // Revision 1.6  2007/01/11 14:07:42  cocoa
273 // -- changed names to arguments called "rsh"
274 //
275 // Revision 1.5  2006/12/06 17:27:29  cocoa
276 // -- removed #include "config.H"
277 //
278 // Revision 1.4  2006/11/24 17:22:05  cocoa
279 // -- removed OpenMathFwd.H
280 //
281 // Revision 1.3  2006/11/02 13:25:44  cocoa
282 // Simplification of header files: the OpenMath classes have been renamed.
283 // Many minor consequential changes.
284 //
285 // Revision 1.2  2006/10/06 14:04:15  cocoa
286 // Corrected position of #ifndef in header files.
287 // Separated CoCoA_ASSERT into assert.H from config.H;
288 // many minor consequential changes (have to #include assert.H).
289 // A little tidying of #include directives (esp. in Max's code).
290 //
291 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
292 // Imported files
293 //
294 // Revision 1.4  2006/05/12 16:10:58  cocoa
295 // Added OpenMathFwd.H, and tidied OpenMath.H.
296 // Many consequential but trivial changes.
297 //
298 // Revision 1.3  2006/03/27 12:21:26  cocoa
299 // Minor silly changes to reduce number of complaints from some compiler or other.
300 //
301 // Revision 1.2  2006/03/12 21:28:34  cocoa
302 // Major check in after many changes
303 //
304 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
305 // Imported files
306 //
307 // Revision 1.4  2005/10/14 15:25:07  cocoa
308 // Major tidying and cleaning to small prime finite fields.
309 // Several consequential changes.  Improved their documentation.
310 //
311 // Added Makefile and script to include/CoCoA/ directory to
312 // keep library.H up to date.
313 //
314 // Revision 1.3  2005/10/12 15:52:09  cocoa
315 // Completed test-RingFp1 and corrected/cleaned the SmallFp*
316 // and RingFp* files.
317 //
318 // Some minor tidying elsewhere.
319 //
320 // Revision 1.2  2005/10/11 16:37:30  cocoa
321 // Added new small prime finite field class (see RingFpDouble).
322 //
323 // Cleaned makefiles and configuration script.
324 //
325 // Tidied PPMonoid code (to eliminate compiler warnings).
326 //
327 // Fixed bug in RingFloat::myIsInteger.
328 //
329 // Revision 1.1  2005/09/22 18:04:17  cocoa
330 // It compiles; the tests run OK.  The examples compile.
331 // No documentation -- the mindless eurocrats have rendered
332 // me mindless too.
333 //
334 
335 #endif
336