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