1 // Copyright (c) 2005-2008,2014 John Abbott 2 3 // This file is part of the source of CoCoALib, the CoCoA Library. 4 5 // CoCoALib is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 10 // CoCoALib is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with CoCoALib. If not, see <http://www.gnu.org/licenses/>. 17 18 #include "CoCoA/OrdvArith.H" 19 20 #include "CoCoA/BigIntOps.H" 21 #include "CoCoA/CanonicalHom.H" 22 #include "CoCoA/DenseMatrix.H" 23 #include "CoCoA/MatrixForOrdering.H" 24 #include "CoCoA/MatrixOps.H" 25 #include "CoCoA/PPOrdering.H" 26 #include "CoCoA/PREPROCESSOR_DEFNS.H" 27 #include "CoCoA/QuotientRing.H" 28 #include "CoCoA/RingFp.H" 29 #include "CoCoA/RingHom.H" 30 #include "CoCoA/RingQQ.H" 31 #include "CoCoA/RingZZ.H" 32 #include "CoCoA/assert.H" 33 #include "CoCoA/config.H" 34 #include "CoCoA/convert.H" 35 #include "CoCoA/degree.H" 36 #include "CoCoA/error.H" 37 #include "CoCoA/matrix.H" 38 39 40 #include <iostream> 41 using std::ostream; 42 using std::endl; 43 //#include <vector> 44 using std::vector; 45 #include <limits> 46 using std::numeric_limits; 47 #include <algorithm> 48 using std::find; 49 using std::copy; 50 //using std::swap; 51 52 53 namespace CoCoA 54 { 55 base(long NumIndets,long GradingDim,long NumOrdvEntries)56 OrdvArith::base::base(long NumIndets, long GradingDim, long NumOrdvEntries): 57 IntrusiveReferenceCount(), 58 myNumIndets(NumIndets), 59 myGradingDim(GradingDim), 60 myOrdvBuffer(NumOrdvEntries), 61 myExpvBuffer(NumIndets) 62 { 63 CoCoA_ASSERT(NumIndets > 0); 64 CoCoA_ASSERT(NumIndets < 1000000); // complain about ridiculously large number of indets 65 CoCoA_ASSERT(GradingDim <= NumIndets); 66 CoCoA_ASSERT(NumOrdvEntries >= NumIndets); 67 myBitsPerOrdvEntry = numeric_limits<SmallExponent_t>::digits; 68 myPackingDensity = numeric_limits<OrdvElem>::digits / myBitsPerOrdvEntry; 69 CoCoA_ASSERT(myPackingDensity >= 1); 70 // Recompute myBitsPerOrdvEntry; this may increase the value (safely, of course)... 71 myBitsPerOrdvEntry = numeric_limits<OrdvElem>::digits / myPackingDensity; 72 CoCoA_ASSERT(myPackingDensity == 1 || myBitsPerOrdvEntry < numeric_limits<OrdvElem>::digits); 73 if (myPackingDensity == 1) // special case because shift op not defined if shift >= wordsize 74 myOrdvMask = numeric_limits<OrdvElem>::max(); 75 else 76 myOrdvMask = (static_cast<OrdvElem>(1) << myBitsPerOrdvEntry) - 1; 77 CoCoA_ASSERT(myOrdvMask != 0); 78 // Reset myOrdvWords to the correct value... 79 myOrdvWords = 1 + (NumOrdvEntries-1)/myPackingDensity; 80 myOrdvWordsForCmp = 1 + (myNumIndets-1)/myPackingDensity; 81 82 myRefCountZero(); 83 } 84 85 ~base()86 OrdvArith::base::~base() 87 {} 88 89 90 myAssignZero(OrdvElem * ordv)91 void OrdvArith::base::myAssignZero(OrdvElem* ordv) const 92 { 93 for (long i=0; i < myOrdvWords; ++i) 94 ordv[i] = 0; 95 } 96 97 myAssign(OrdvElem * dest,const OrdvElem * src)98 void OrdvArith::base::myAssign(OrdvElem* dest, const OrdvElem* src) const 99 { 100 // std::copy(&src[0], &src[myOrdvWords], &dest[0]); // seems slightly slower 101 for (long i=0; i < myOrdvWords; ++i) 102 dest[i] = src[i]; 103 } 104 105 mySwap(OrdvElem * ordv1,OrdvElem * ordv2)106 void OrdvArith::base::mySwap(OrdvElem* ordv1, OrdvElem* ordv2) const 107 { 108 // if (ordv1 == ordv2) return; // worth checking this special case??? 109 for (long i=0; i < myOrdvWords; ++i) 110 std::swap(ordv1[i], ordv2[i]); 111 } 112 113 myMulIndetPower(OrdvElem * ordv,long var,long exp)114 void OrdvArith::base::myMulIndetPower(OrdvElem* ordv, long var, long exp) const 115 { 116 CoCoA_ASSERT(exp >= 0); 117 CoCoA_ASSERT(0 <= var && var < myNumIndets); 118 vector<long> PowerExpv(myNumIndets); // should be member of OrdvArith::base? Use myExpvBuffer??? 119 PowerExpv[var] = exp; 120 vector<OrdvElem> PowerOrdv(myOrdvWords); // should be member of OrdvArith::base? Use myOrdvBuffer???? 121 myAssignFromExpv(&PowerOrdv[0], PowerExpv); 122 myMul(ordv, ordv, &PowerOrdv[0]); 123 } 124 125 myPower(OrdvElem * ordv,const OrdvElem * ordv1,long LongExp)126 void OrdvArith::base::myPower(OrdvElem* ordv, const OrdvElem* ordv1, long LongExp) const 127 { 128 CoCoA_ASSERT(LongExp >= 0); 129 #ifdef CoCoA_DEBUG 130 myPowerOverflowCheck(ordv1, LongExp); 131 #endif 132 const OrdvElem exp = static_cast<OrdvElem>(LongExp); 133 if (exp > myOrdvMask) 134 CoCoA_THROW_ERROR(ERR::ExpTooBig, "OrdvArith::myPower"); 135 for (long i=0; i < myOrdvWords; ++i) 136 ordv[i] = exp*ordv1[i]; 137 } 138 139 myPowerOverflowCheck(const OrdvElem * ordv,long LongExp)140 void OrdvArith::base::myPowerOverflowCheck(const OrdvElem* ordv, long LongExp) const 141 { 142 if (LongExp == 0 || LongExp == 1) return; 143 CoCoA_ASSERT(LongExp >= 0); 144 if (static_cast<unsigned long>(LongExp) > myOrdvMask) 145 CoCoA_THROW_ERROR(ERR::ExpTooBig, "OrdvArith::myPower"); 146 const OrdvElem exp = static_cast<OrdvElem>(LongExp); 147 // ??? Is it worth uncommenting these two shortcuts??? 148 // if (pow == 0) { myAssignZero(ordv); return; } 149 // if (pow == 1) { myAssign(ordv, ordv1); return; } 150 #ifdef CoCoA_THREADSAFE_HACK 151 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 152 #endif 153 myDecompress(myOrdvBuffer, ordv, myNumIndets); 154 for (long i=0; i < myNumIndets; ++i) 155 { 156 // Check for ordv element overflow. 157 if (myOrdvBuffer[i] > 0 && myOrdvMask/myOrdvBuffer[i] < exp) 158 CoCoA_THROW_ERROR(ERR::ExpTooBig, "OrdvArith::myPower"); 159 } 160 } 161 162 myStdDeg(const OrdvElem * ordv)163 long OrdvArith::base::myStdDeg(const OrdvElem* ordv) const 164 { 165 #ifdef CoCoA_THREADSAFE_HACK 166 vector<long> myExpvBuffer(myNumIndets); // NB hides data member! 167 #endif 168 myComputeExpv(myExpvBuffer, ordv); 169 long d=0; 170 for (long i=0; i < myNumIndets; ++i) 171 d += myExpvBuffer[i]; // ignore possible overflow 172 return d; 173 } 174 175 myWDeg(degree & d,const OrdvElem * ordv)176 void OrdvArith::base::myWDeg(degree& d, const OrdvElem* ordv) const 177 { 178 CoCoA_ASSERT(GradingDim(d) == myGradingDim); 179 #ifdef CoCoA_THREADSAFE_HACK 180 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 181 #endif 182 myDecompress(myOrdvBuffer, ordv, myGradingDim); 183 for (long i=0; i < myGradingDim; ++i) 184 SetComponent(d, i, myOrdvBuffer[i]); 185 } 186 187 myCmpWDegPartial(const OrdvElem * ordv1,const OrdvElem * ordv2,long PartialGrDim)188 int OrdvArith::base::myCmpWDegPartial(const OrdvElem* ordv1, const OrdvElem* ordv2, long PartialGrDim) const // assumes GrDim >= 0 189 { 190 CoCoA_ASSERT(0 <= PartialGrDim && PartialGrDim <= myGradingDim); 191 const long last = PartialGrDim/myPackingDensity; 192 for (long i=0; i < last; ++i) 193 if (ordv1[i] != ordv2[i]) return (ordv1[i] > ordv2[i])?1:-1; 194 const long ShiftCount = (last+1)*myPackingDensity - PartialGrDim; 195 if (ShiftCount == myPackingDensity) return 0; 196 CoCoA_ASSERT(myPackingDensity > 1 && myBitsPerOrdvEntry < numeric_limits<OrdvElem>::digits); 197 // Reach here only if myPackingDensity > 1, so myBitsPerOrdvEntry < wordsize 198 const OrdvElem last1 = ordv1[last] >> (ShiftCount*myBitsPerOrdvEntry); 199 const OrdvElem last2 = ordv2[last] >> (ShiftCount*myBitsPerOrdvEntry); 200 if (last1 == last2) return 0; 201 if (last1 > last2) return 1; 202 return -1; 203 } 204 205 myIsZero(const OrdvElem * ordv)206 bool OrdvArith::base::myIsZero(const OrdvElem* ordv) const 207 { 208 for (long i=0; i < myOrdvWordsForCmp; ++i) 209 if (ordv[i] != 0) return false; 210 return true; 211 } 212 213 214 // Simple rather than efficient. myIsIndet(long & index,const OrdvElem * ordv)215 bool OrdvArith::base::myIsIndet(long& index, const OrdvElem* ordv) const 216 { 217 #ifdef CoCoA_THREADSAFE_HACK 218 vector<long> myExpvBuffer(myNumIndets); // NB hides data member! 219 #endif 220 myComputeExpv(myExpvBuffer, ordv); 221 222 long j = myNumIndets; 223 for (long i = 0; i < myNumIndets; ++i) 224 { 225 if (myExpvBuffer[i] == 0) continue; 226 if (j != myNumIndets || myExpvBuffer[i] != 1) return false; 227 j = i; 228 } 229 if (j == myNumIndets) return false; 230 index = j; 231 return true; 232 } 233 234 myOrdvGetNth(const OrdvElem * ordv,long n)235 OrdvArith::OrdvElem OrdvArith::base::myOrdvGetNth(const OrdvElem* ordv, long n) const 236 { 237 CoCoA_ASSERT(n < myOrdvWords*myPackingDensity); 238 const long posn = n/myPackingDensity; 239 const long n_shifts = myPackingDensity-1 - (n%myPackingDensity); 240 const OrdvElem tmp = ordv[posn] >> (n_shifts * myBitsPerOrdvEntry); // NB shift amount is less than word width! 241 return (tmp & myOrdvMask); 242 } 243 244 myCompress(OrdvElem * ordv,const vector<OrdvElem> & buffer)245 void OrdvArith::base::myCompress(OrdvElem* ordv, const vector<OrdvElem>& buffer) const 246 { 247 if (myPackingDensity == 1) 248 { 249 std::copy(buffer.begin(), buffer.end(), ordv); 250 return; 251 } 252 long posn = 0; 253 for (long i=0; i < myOrdvWords; ++i) 254 { 255 OrdvElem word = 0; // this value is totally irrelevant, it gets shifted into "hyperspace" 256 for (long j=0; j < myPackingDensity; ++j) 257 { 258 word <<= myBitsPerOrdvEntry; // ok because myBitsPerOrdvEntry < wordsize!!! 259 if (posn < myNumIndets) word += buffer[posn]; 260 ++posn; 261 } 262 ordv[i] = word; 263 } 264 } 265 266 myDecompress(vector<OrdvElem> & buffer,const OrdvElem * ordv,long NumCompts)267 void OrdvArith::base::myDecompress(vector<OrdvElem>& buffer, const OrdvElem* ordv, long NumCompts) const 268 { 269 if (myPackingDensity == 1) 270 { 271 std::copy(&ordv[0], &ordv[NumCompts], buffer.begin()); 272 return; 273 } 274 long BasePosn = 0; 275 for (long i=0; i < myOrdvWords; ++i) 276 { 277 OrdvElem word = ordv[i]; 278 for (long j=myPackingDensity; j-- > 0;) 279 { 280 if (BasePosn + j < NumCompts) 281 buffer[BasePosn + j] = (word & myOrdvMask); 282 word >>= myBitsPerOrdvEntry; // ok because myBitsPerOrdvEntry < wordsize!!! 283 } 284 BasePosn += myPackingDensity; 285 } 286 } 287 288 289 290 //--------------------------------------------------------------------------- 291 // LexImpl 292 LexImpl(long NumIndets)293 OrdvArith::LexImpl::LexImpl(long NumIndets): 294 base(NumIndets, 0, NumIndets) 295 {} 296 297 myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)298 void OrdvArith::LexImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const 299 { 300 #ifdef CoCoA_THREADSAFE_HACK 301 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 302 #endif 303 for (long i=0; i < myNumIndets; ++i) 304 myOrdvBuffer[i] = expv[i]; 305 myCompress(ordv, myOrdvBuffer); 306 } 307 308 myComputeExpv(vector<long> & expv,const OrdvElem * ordv)309 void OrdvArith::LexImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const 310 { 311 #ifdef CoCoA_THREADSAFE_HACK 312 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 313 #endif 314 myDecompress(myOrdvBuffer, ordv, myNumIndets); 315 for (long i=0; i < myNumIndets; ++i) 316 expv[i] = NumericCast<long>(myOrdvBuffer[i]); 317 } 318 319 myExponent(const OrdvElem * ordv,long var)320 long OrdvArith::LexImpl::myExponent(const OrdvElem* ordv, long var) const 321 { 322 return NumericCast<long>(myOrdvGetNth(ordv, var)); 323 } 324 325 myOutputSelf(ostream & out)326 void OrdvArith::LexImpl::myOutputSelf(ostream& out) const 327 { 328 if (!out) return; // short-cut for bad ostreams 329 out << "OrdvArith::LexImpl(" << myNumIndets << ")"; 330 } 331 332 333 334 //--------------------------------------------------------------------------- 335 // StdDegLexImpl 336 StdDegLexImpl(long NumIndets)337 OrdvArith::StdDegLexImpl::StdDegLexImpl(long NumIndets): 338 base(NumIndets, 1, NumIndets) 339 {} 340 341 myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)342 void OrdvArith::StdDegLexImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const 343 { 344 OrdvElem deg = expv[0]; 345 for (long i=1; i < myNumIndets; ++i) 346 { 347 CoCoA_ASSERT("Exponent overflow" && deg <= myOrdvMask-expv[i]); 348 deg += expv[i]; 349 } 350 #ifdef CoCoA_THREADSAFE_HACK 351 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 352 #endif 353 myOrdvBuffer[0] = deg; 354 for (long i=1; i < myNumIndets; ++i) 355 myOrdvBuffer[i] = expv[i-1]; 356 357 myCompress(ordv, myOrdvBuffer); 358 } 359 360 myComputeExpv(vector<long> & expv,const OrdvElem * ordv)361 void OrdvArith::StdDegLexImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const 362 { 363 #ifdef CoCoA_THREADSAFE_HACK 364 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 365 #endif 366 myDecompress(myOrdvBuffer, ordv, myNumIndets); 367 OrdvElem expN = myOrdvBuffer[0]; 368 for (long i=1; i < myNumIndets; ++i) 369 { 370 const OrdvElem& ordvi = myOrdvBuffer[i]; 371 expN -= ordvi; 372 expv[i-1] = ordvi; 373 } 374 expv[myNumIndets-1] = expN; 375 } 376 377 myStdDeg(const OrdvElem * ordv)378 long OrdvArith::StdDegLexImpl::myStdDeg(const OrdvElem* ordv) const 379 { 380 #ifdef CoCoA_THREADSAFE_HACK 381 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 382 #endif 383 myDecompress(myOrdvBuffer, ordv, 1); 384 return myOrdvBuffer[0]; 385 } 386 387 myExponent(const OrdvElem * ordv,long var)388 long OrdvArith::StdDegLexImpl::myExponent(const OrdvElem* ordv, long var) const 389 { 390 if (var < myNumIndets-1) return NumericCast<long>(myOrdvGetNth(ordv, var+1)); 391 #ifdef CoCoA_THREADSAFE_HACK 392 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 393 #endif 394 myDecompress(myOrdvBuffer, ordv, myNumIndets); 395 OrdvElem ans = myOrdvBuffer[0]; 396 for (long i=1; i < myNumIndets; ++i) 397 ans -= myOrdvBuffer[i]; // NB this cannot underflow if degree has not overflowed 398 return NumericCast<long>(ans); 399 } 400 401 myOutputSelf(ostream & out)402 void OrdvArith::StdDegLexImpl::myOutputSelf(ostream& out) const 403 { 404 if (!out) return; // short-cut for bad ostreams 405 out << "OrdvArith::StdDegLexImpl(" << myNumIndets << ")"; 406 } 407 408 409 410 //--------------------------------------------------------------------------- 411 // StdDegRevLexImpl 412 StdDegRevLexImpl(long NumIndets)413 OrdvArith::StdDegRevLexImpl::StdDegRevLexImpl(long NumIndets): 414 base(NumIndets, 1, NumIndets) 415 {} 416 417 myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)418 void OrdvArith::StdDegRevLexImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const 419 { 420 OrdvElem deg = expv[0]; 421 for (long i=1; i < myNumIndets; ++i) 422 { 423 CoCoA_ASSERT("Negative exponent" && expv[i] >= 0); 424 CoCoA_ASSERT("Exponent overflow" && static_cast<unsigned long>(expv[i]) <= myOrdvMask-deg); 425 deg += expv[i]; 426 } 427 #ifdef CoCoA_THREADSAFE_HACK 428 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 429 #endif 430 myOrdvBuffer[0] = deg; 431 for (long i=1; i < myNumIndets; ++i) 432 myOrdvBuffer[i] = deg - expv[myNumIndets - i]; 433 434 myCompress(ordv, myOrdvBuffer); 435 } 436 437 myComputeExpv(vector<long> & expv,const OrdvElem * ordv)438 void OrdvArith::StdDegRevLexImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const 439 { 440 #ifdef CoCoA_THREADSAFE_HACK 441 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 442 #endif 443 myDecompress(myOrdvBuffer, ordv, myNumIndets); 444 const OrdvElem deg = myOrdvBuffer[0]; 445 OrdvElem exp0 = (2-myNumIndets)*deg; // may HARMLESSLY become "negative" or "overflow" 446 for (long i=1; i < myNumIndets; ++i) 447 { 448 const OrdvElem ordvi = myOrdvBuffer[i]; 449 exp0 += ordvi; 450 expv[myNumIndets-i] = deg - ordvi; 451 } 452 expv[0] = exp0; 453 } 454 455 myStdDeg(const OrdvElem * ordv)456 long OrdvArith::StdDegRevLexImpl::myStdDeg(const OrdvElem* ordv) const 457 { 458 #ifdef CoCoA_THREADSAFE_HACK 459 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 460 #endif 461 myDecompress(myOrdvBuffer, ordv, 1); 462 return myOrdvBuffer[0]; 463 } 464 465 myExponent(const OrdvElem * ordv,long var)466 long OrdvArith::StdDegRevLexImpl::myExponent(const OrdvElem* ordv, long var) const 467 { 468 if (var != 0) return NumericCast<long>(myOrdvGetNth(ordv, 0) - myOrdvGetNth(ordv, myNumIndets-var)); 469 470 #ifdef CoCoA_THREADSAFE_HACK 471 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 472 #endif 473 myDecompress(myOrdvBuffer, ordv, myNumIndets); 474 OrdvElem ans = (2-myNumIndets)*myOrdvBuffer[0]; // may HARMLESSLY become "negative" or overflow 475 for (long i=1; i < myNumIndets; ++i) 476 ans += myOrdvBuffer[i]; 477 return NumericCast<long>(ans); 478 } 479 480 myOutputSelf(ostream & out)481 void OrdvArith::StdDegRevLexImpl::myOutputSelf(ostream& out) const 482 { 483 if (!out) return; // short-cut for bad ostreams 484 out << "OrdvArith::StdDegRevLexImpl(" << myNumIndets << ")"; 485 } 486 487 488 489 //--------------------------------------------------------------------------- 490 // StdDegRevLexImpl2 491 StdDegRevLexImpl2(long NumIndets)492 OrdvArith::StdDegRevLexImpl2::StdDegRevLexImpl2(long NumIndets): 493 base(NumIndets, 1, NumIndets) 494 {} 495 496 myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)497 void OrdvArith::StdDegRevLexImpl2::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const 498 { 499 OrdvElem PartialSum = 0; 500 long j = myNumIndets-1; 501 #ifdef CoCoA_THREADSAFE_HACK 502 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 503 #endif 504 for (long i=0; i < myNumIndets; ++i, --j) 505 { 506 CoCoA_ASSERT("Exponent overflow" && NumericCast<OrdvElem>(expv[i]) <= myOrdvMask-PartialSum); 507 PartialSum += expv[i]; 508 myOrdvBuffer[j] = PartialSum; 509 } 510 511 myCompress(ordv, myOrdvBuffer); 512 } 513 514 myComputeExpv(vector<long> & expv,const OrdvElem * ordv)515 void OrdvArith::StdDegRevLexImpl2::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const 516 { 517 #ifdef CoCoA_THREADSAFE_HACK 518 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 519 #endif 520 myDecompress(myOrdvBuffer, ordv, myNumIndets); 521 expv[0] = myOrdvBuffer[myNumIndets-1]; 522 long i = myNumIndets-1; 523 for (long j=1; j < myNumIndets; ++j, --i) 524 expv[i] = myOrdvBuffer[j-1] - myOrdvBuffer[j]; 525 } 526 527 myStdDeg(const OrdvElem * ordv)528 long OrdvArith::StdDegRevLexImpl2::myStdDeg(const OrdvElem* ordv) const 529 { 530 #ifdef CoCoA_THREADSAFE_HACK 531 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 532 #endif 533 myDecompress(myOrdvBuffer, ordv, 1); 534 return myOrdvBuffer[0]; 535 } 536 537 myExponent(const OrdvElem * ordv,long var)538 long OrdvArith::StdDegRevLexImpl2::myExponent(const OrdvElem* ordv, long var) const 539 { 540 if (var == 0) return NumericCast<long>(myOrdvGetNth(ordv, myNumIndets-1)); 541 return NumericCast<long>(myOrdvGetNth(ordv, myNumIndets-var-1) - myOrdvGetNth(ordv, myNumIndets-var)); 542 } 543 544 myOutputSelf(ostream & out)545 void OrdvArith::StdDegRevLexImpl2::myOutputSelf(ostream& out) const 546 { 547 if (!out) return; // short-cut for bad ostreams 548 out << "OrdvArith::StdDegRevLexImpl2(" << myNumIndets << ")"; 549 } 550 551 552 553 //--------------------------------------------------------------------------- 554 // MatrixOrderingImpl 555 MatrixOrderingImpl(long NumIndets,long GradingDim,const ConstMatrixView &)556 OrdvArith::MatrixOrderingImpl::MatrixOrderingImpl(long NumIndets, long GradingDim, const ConstMatrixView& /*OrderMatrix*/): 557 base(NumIndets, GradingDim, NumIndets) 558 { 559 CoCoA_THROW_ERROR(ERR::NYI, "MatrixOrderingImpl"); 560 // CoCoA_ASSERT(myGradingDim < NumRows(OrderMatrix)); 561 // CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets); 562 // CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets); 563 // // Check that the matrix entries are non-negative 564 // for (long i=0; i < myNumIndets; ++i) 565 // for (long j=0; j < myNumIndets; ++j) 566 // CoCoA_ASSERT(myOrderMatrix[i][j] >= 0); 567 } 568 569 myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)570 void OrdvArith::MatrixOrderingImpl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const 571 { 572 #ifdef CoCoA_THREADSAFE_HACK 573 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 574 #endif 575 for (long i=0; i < myNumIndets; ++i) 576 { 577 myOrdvBuffer[i] = 0; 578 for (long j=0; j < myNumIndets; ++j) 579 myOrdvBuffer[i] += myOrderMatrix[i][j]*expv[j]; 580 } 581 582 myCompress(ordv, myOrdvBuffer); 583 } 584 585 myComputeExpv(vector<long> & expv,const OrdvElem * ordv)586 void OrdvArith::MatrixOrderingImpl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const 587 { 588 #ifdef CoCoA_THREADSAFE_HACK 589 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 590 #endif 591 myDecompress(myOrdvBuffer, ordv, myNumIndets); 592 for (long i=0; i < myNumIndets; ++i) 593 { 594 long deg = 0; 595 for (long j=0; j < myNumIndets; ++j) 596 deg += myAdjointOrderMatrix[i][j] * myOrdvBuffer[j]; 597 expv[i] = deg/myOrderMatrixDet; 598 } 599 } 600 601 myExponent(const OrdvElem * ordv,long var)602 long OrdvArith::MatrixOrderingImpl::myExponent(const OrdvElem* ordv, long var) const 603 { 604 #ifdef CoCoA_THREADSAFE_HACK 605 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 606 #endif 607 myDecompress(myOrdvBuffer, ordv, myNumIndets); 608 OrdvElem ans = 0; 609 for (long j=0; j < myNumIndets; ++j) 610 ans += myAdjointOrderMatrix[var][j] * myOrdvBuffer[j]; 611 ans /= myOrderMatrixDet; 612 return NumericCast<long>(ans); 613 } 614 615 616 myOutputSelf(ostream & out)617 void OrdvArith::MatrixOrderingImpl::myOutputSelf(ostream& out) const 618 { 619 if (!out) return; // short-cut for bad ostreams 620 621 out << "OrdArith::MatrixOrdering(GradingDim=" << myGradingDim << ", "; 622 // out << "PPOrdering(GRADING=matrix(["; 623 // for (long i=0; i < myGradingDim; ++i) 624 // { 625 // if (i > 0) out << ", "; 626 // out << "["; 627 // for (long j=0; j < myNumIndets; ++j) 628 // { 629 // if (j > 0) out << ", "; 630 // out << myOrderMatrix[i][j]; 631 // } 632 // out << "]"; 633 // } 634 // out << "]), "; 635 out << "matrix(["; 636 for (long i=0; i < myNumIndets; ++i) //??? start from myGradingDim??? 637 { 638 if (i > 0) out << ", "; 639 out << "["; 640 for (long j=0; j < myNumIndets; ++j) 641 { 642 if (j > 0) out << ", "; 643 out << myOrderMatrix[i][j]; 644 } 645 out << "]"; 646 } 647 out << "]))"; 648 } 649 650 651 652 653 //-------------------- MatrixOrderingMod32749Impl -------------------- 654 MatrixOrderingMod32749Impl(long NumIndets,long GradingDim,const ConstMatrixView & OrderMatrix)655 OrdvArith::MatrixOrderingMod32749Impl::MatrixOrderingMod32749Impl(long NumIndets, long GradingDim, const ConstMatrixView& OrderMatrix): 656 base(NumIndets, GradingDim, NumIndets) 657 { 658 // std::cout << "------ctor-MatrixOrderingMod32749Impl-called" << std::endl; 659 CoCoA_ASSERT(NumRows(OrderMatrix) == NumIndets); 660 CoCoA_ASSERT(NumCols(OrderMatrix) == NumIndets); 661 CoCoA_ASSERT(IsZZ(RingOf(OrderMatrix))||IsQQ(RingOf(OrderMatrix))); 662 if (!IsTermOrdering(OrderMatrix)) 663 CoCoA_THROW_ERROR(ERR::NotTermOrdering, "OrdvArith::MatrixOrderingMod32749Impl::MatrixOrderingMod32749Impl"); 664 665 const QuotientRing Fp = NewRingFp(32749,GlobalSettings::NonNegResidues); 666 matrix M(NewDenseMat(Fp, NumIndets, NumIndets)); 667 const RingHom phi = CanonicalHom(RingOf(OrderMatrix), Fp); 668 669 for (long i=0; i < GradingDim; ++i) 670 for (long j=0; j < NumCols(OrderMatrix); ++j) 671 if (sign(OrderMatrix(i,j)) < 0) CoCoA_THROW_ERROR(ERR::NYI, "MatrixOrderingMod32749Impl: temporarily forcing weights to be non-negative"); 672 matrix PosOrdMat = MakeTermOrd(OrderMatrix); 673 for (long i=0; i < myNumIndets; ++i) 674 for (long j=0; j < myNumIndets; ++j) 675 { 676 if (PosOrdMat(i,j)>= 32749) CoCoA_THROW_ERROR(ERR::ArgTooBig, "OrdvArith::MatrixOrderingMod32749Impl ctor"); 677 SetEntry(M, i, j, phi(PosOrdMat(i, j))); 678 } 679 matrix InvM = inverse(M); 680 681 BigInt tmp; 682 myOrderMatrix.resize(myNumIndets, vector<int>(myNumIndets)); 683 myInverseOrderMatrix.resize(myNumIndets, vector<int>(myNumIndets)); 684 for (long i=0; i < myNumIndets; ++i) 685 for (long j=0; j < myNumIndets; ++j) 686 { 687 myOrderMatrix[i][j] = ConvertTo<long>(PosOrdMat(i,j)); 688 myInverseOrderMatrix[i][j] = ConvertTo<long>(InvM(i,j)); 689 } 690 691 #ifdef CoCoA_DEBUG 692 // Verify that myOrderMatrix is all non-negative 693 for (long i=0; i < NumRows(M); ++i) 694 for (long j=0; j < NumCols(M); ++j) 695 CoCoA_ASSERT(myOrderMatrix[i][j] >= 0); 696 // Verify that myOrderMatrix*myInverseOrderMatrix is the identity 697 for (long i=0; i < myNumIndets; ++i) 698 { 699 for (long j=0; j < myNumIndets; ++j) 700 { 701 int prod_ij = 0; 702 for (long k=0; k < myNumIndets; ++k) 703 prod_ij += (myOrderMatrix[i][k] * myInverseOrderMatrix[k][j])%32749; 704 if (i == j) CoCoA_ASSERT("BAD INVERSE" && prod_ij%32749 == 1); 705 else CoCoA_ASSERT("BAD INVERSE" && prod_ij%32749 == 0); 706 } 707 } 708 #endif 709 myRefCountZero(); 710 } 711 712 myAssignFromExpv(OrdvElem * ordv,const vector<long> & expv)713 void OrdvArith::MatrixOrderingMod32749Impl::myAssignFromExpv(OrdvElem* ordv, const vector<long>& expv) const 714 { 715 #ifdef CoCoA_THREADSAFE_HACK 716 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 717 #endif 718 for (long i=0; i < myNumIndets; ++i) 719 { 720 myOrdvBuffer[i] = 0; 721 for (long j=0; j < myNumIndets; ++j) 722 myOrdvBuffer[i] += myOrderMatrix[i][j]*expv[j]; 723 } 724 725 myCompress(ordv, myOrdvBuffer); 726 } 727 728 myComputeExpv(vector<long> & expv,const OrdvElem * ordv)729 void OrdvArith::MatrixOrderingMod32749Impl::myComputeExpv(vector<long>& expv, const OrdvElem* ordv) const 730 { 731 #ifdef CoCoA_THREADSAFE_HACK 732 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 733 #endif 734 myDecompress(myOrdvBuffer, ordv, myNumIndets); 735 for (long i=0; i < myNumIndets; ++i) 736 { 737 unsigned long deg = 0; 738 for (long j=0; j < myNumIndets; ++j) 739 { 740 deg += (myInverseOrderMatrix[i][j] * myOrdvBuffer[j]); 741 if (deg>46336*32749) deg -= 46336*32749; 742 } 743 expv[i] = deg%32749; 744 } 745 } 746 747 myExponent(const OrdvElem * ordv,long var)748 long OrdvArith::MatrixOrderingMod32749Impl::myExponent(const OrdvElem* ordv, long var) const 749 { 750 #ifdef CoCoA_THREADSAFE_HACK 751 vector<OrdvElem> myOrdvBuffer(myNumIndets); // NB hides data member! 752 #endif 753 myDecompress(myOrdvBuffer, ordv, myNumIndets); 754 OrdvElem ans = 0; 755 for (long j=0; j < myNumIndets; ++j) 756 { 757 ans += (myInverseOrderMatrix[var][j] * myOrdvBuffer[j]); 758 if (ans > 46336*32749) ans -= 46336*32749; 759 } 760 return ans%32749; // no need to use NumericCast here, overflow can never occur 761 } 762 763 myOutputSelf(ostream & out)764 void OrdvArith::MatrixOrderingMod32749Impl::myOutputSelf(ostream& out) const 765 { 766 if (!out) return; // short-cut for bad ostreams 767 768 out << "OrdvArith::MatrixOrdering(GradingDim=" << myGradingDim << ", "; 769 // out << "PPOrdering(GRADING=matrix(["; 770 // for (long i=0; i < myGradingDim; ++i) 771 // { 772 // if (i > 0) out << ", "; 773 // out << "["; 774 // for (long j=0; j < myNumIndets; ++j) 775 // { 776 // if (j > 0) out << ", "; 777 // out << myOrderMatrix[i][j]; 778 // } 779 // out << "]"; 780 // } 781 // out << "]), "; 782 out << "matrix(["; 783 for (long i=0; i < myNumIndets; ++i) 784 { 785 if (i > 0) out << ", "; 786 out << "["; 787 for (long j=0; j < myNumIndets; ++j) 788 { 789 if (j > 0) out << ", "; 790 out << myOrderMatrix[i][j]; 791 } 792 out << "]"; 793 } 794 out << "]))"; 795 } 796 797 798 // void OrdvArith::MatrixOrderingMod32749Impl::mySetMatrix(const matrix& M) 799 // { 800 // CoCoA_ASSERT(NumRows(M) == myNumIndets); 801 // CoCoA_ASSERT(NumCols(M) == myNumIndets); 802 // BigInt tmp; 803 804 // for (long i=0; i < myNumIndets; ++i) 805 // for (long j=0; j < myNumIndets; ++j) 806 // { 807 // if (!IsInteger(tmp, M(i, j))) 808 // CoCoA_THROW_ERROR("entry of MatrixOrdering is not integer","MatrixOrderingMod32749Impl"); 809 // if (!convert(myInverseOrderMatrix[i][j], tmp)) 810 // CoCoA_THROW_ERROR("entry of MatrixOrdering is not integer","MatrixOrderingMod32749Impl"); 811 // } 812 // } 813 814 815 // void OrdvArith::MatrixOrderingMod32749Impl::mySetInverseMatrixTmp(const matrix& /*M*/) 816 // { /*???*/ } 817 818 819 820 //--------------------------------------------------------------------------- 821 NewOrdvArith(const PPOrdering & PPO)822 OrdvArith::reference NewOrdvArith(const PPOrdering& PPO) 823 { 824 // std::cout << "--------NewOrdvArith-called" << std::endl; 825 if (IsLex(PPO)) 826 return OrdvArith::reference(new OrdvArith::LexImpl(NumIndets(PPO))); 827 if (IsStdDegLex(PPO)) 828 return OrdvArith::reference(new OrdvArith::StdDegLexImpl(NumIndets(PPO))); 829 if (IsStdDegRevLex(PPO)) 830 return OrdvArith::reference(new OrdvArith::StdDegRevLexImpl(NumIndets(PPO))); 831 832 // If we get here, we have a matrix ordering. 833 834 const long n = NumIndets(PPO); 835 const long g = GradingDim(PPO); 836 837 ConstMatrixView M(OrdMat(PPO)); 838 839 CoCoA_ASSERT(NumRows(M) == n); 840 CoCoA_ASSERT(NumCols(M) == n); 841 CoCoA_ASSERT(g <= n); 842 843 return OrdvArith::reference(new OrdvArith::MatrixOrderingMod32749Impl(n, g, M)); 844 845 // (1) Get matrix M out of the ordering. 846 // (2) Make an equivalent matrix M2 which is strictly positive 847 // (3) Build a MatrixOrderingImpl object with M2, but also need 848 // the transformation matrix to be able to calculate degrees!! 849 } 850 851 852 std::ostream& operator<<(std::ostream& out, const OrdvArith::reference& OA) 853 { 854 if (!out) return out; // short-cut for bad ostreams 855 OA->myOutputSelf(out); 856 return out; 857 } 858 859 860 } // end of namespace CoCoA 861 862 863 // RCS header/log 864 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/OrdvArith.C,v 1.51 2020/06/17 15:49:24 abbott Exp $ 865 // $Log: OrdvArith.C,v $ 866 // Revision 1.51 2020/06/17 15:49:24 abbott 867 // Summary: Changed CoCoA_ERROR into CoCoA_THROW_ERROR 868 // 869 // Revision 1.50 2020/02/11 16:56:41 abbott 870 // Summary: Corrected last update (see redmine 969) 871 // 872 // Revision 1.49 2020/02/11 16:12:18 abbott 873 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969 874 // 875 // Revision 1.48 2018/05/18 12:15:04 bigatti 876 // -- renamed IntOperations --> BigIntOps 877 // 878 // Revision 1.47 2018/05/17 15:37:47 bigatti 879 // -- renamed MatrixOperations --> MatrixOps 880 // 881 // Revision 1.46 2017/05/17 15:57:34 bigatti 882 // -- added check for ArgTooBig in MatrixOrderingMod32749Impl ctor 883 // 884 // Revision 1.45 2017/04/18 12:50:06 abbott 885 // Summary: Corrected ifdef use of CoCoA_THREADSAFE_HACK and CoCoA_DEBUG 886 // 887 // Revision 1.44 2016/11/11 14:15:32 abbott 888 // Summary: Added short-cut to operator<< when ostream is in bad state 889 // 890 // Revision 1.43 2015/12/08 14:05:11 abbott 891 // Summary: Renamed NewMatCompleteOrd to MakeTermOrd 892 // 893 // Revision 1.42 2015/12/01 17:34:30 abbott 894 // Summary: Added call to NewMatCompleteOrd to ctor for MatOrdMod32749 895 // 896 // Revision 1.41 2015/12/01 15:58:22 abbott 897 // Summary: Removed call to NewPositiveMat; moved a sanity check 898 // 899 // Revision 1.40 2015/11/30 21:53:55 abbott 900 // Summary: Major update to matrices for orderings (not yet complete, some tests fail) 901 // 902 // Revision 1.39 2015/04/13 14:42:07 abbott 903 // Summary: Added myPowerOverflowCheck (1st version) 904 // Author: JAA 905 // 906 // Revision 1.38 2014/07/31 13:10:46 bigatti 907 // -- GetMatrix(PPO) --> OrdMat(PPO) 908 // -- added OrdMat and GradingMat to PPOrdering, PPMonoid, SparsePolyRing 909 // 910 // Revision 1.37 2014/07/30 14:07:26 abbott 911 // Summary: Changed BaseRing into RingOf 912 // Author: JAA 913 // 914 // Revision 1.36 2014/04/30 16:10:00 abbott 915 // Summary: Removed pointless include 916 // Author: JAA 917 // 918 // Revision 1.35 2014/04/11 15:44:27 abbott 919 // Summary: Renamed MatrixArith to MatrixOperations (in includes) 920 // Author: JAA 921 // 922 // Revision 1.34 2014/01/29 13:06:08 abbott 923 // Summary: Removed irrelevant #include directive 924 // Author: JAA 925 // 926 // Revision 1.33 2014/01/28 16:53:36 abbott 927 // Significant change: code is now threadsafe. 928 // Uses CPP flag CoCoA_THREADSAFE_HACK to select between single-threaded & multi-threaded 929 // code; single-threaded uses a "global" buffer. 930 // 931 // Revision 1.32 2013/05/27 13:09:35 abbott 932 // Added include directive for config.H. 933 // 934 // Revision 1.31 2013/04/24 09:15:08 abbott 935 // Added an assertion. 936 // 937 // Revision 1.30 2013/03/27 11:37:04 abbott 938 // Added new (faster, cleaner) impl for StdDegRevLex. Still no doc though. 939 // 940 // Revision 1.29 2013/03/26 15:45:37 abbott 941 // NOT YET COMPLETE -- just checking in so that CVS compiles!!! 942 // 943 // Revision 1.28 2013/03/15 10:56:39 abbott 944 // Changed OrdvElem into unsigned long. 945 // Corrected evil/subtle bug in CmpWDegPartial. 946 // 947 // Revision 1.27 2013/02/26 21:40:43 abbott 948 // Fixed evil subtle bug: shift operator<< and operator>> are UNDEFINED if 949 // shift amount is greater than or equal to wordsize. NASTY!!! 950 // Added overflow check in power function. 951 // Some minor cleaning. 952 // 953 // Revision 1.26 2012/05/28 09:18:21 abbott 954 // Created IntOperations which gathers together all operations on 955 // integers (both big and small). Many consequential changes. 956 // 957 // Revision 1.25 2012/04/02 17:06:00 bigatti 958 // -- allowing QQ for BaseRing of oder matrices 959 // 960 // Revision 1.24 2012/03/30 17:29:01 bigatti 961 // -- accepting matrices over QQ 962 // 963 // Revision 1.23 2012/02/10 10:28:08 bigatti 964 // -- changed RingZ.H, RingQ.H --> RingZZ.H, RingQQ.H 965 // 966 // Revision 1.22 2012/02/08 16:12:37 bigatti 967 // -- changed: Z,Q -> ZZ,QQ 968 // 969 // Revision 1.21 2011/08/14 15:52:17 abbott 970 // Changed ZZ into BigInt (phase 1: just the library sources). 971 // 972 // Revision 1.20 2011/05/19 14:41:09 abbott 973 // Matrix impl now explicitly requests non-neg residues when creating RingFp. 974 // 975 // Revision 1.19 2011/03/16 15:30:09 abbott 976 // Removed two "unsigned" (exponent args). 977 // 978 // Revision 1.18 2011/03/16 13:22:15 abbott 979 // Added comments (about GrDim) for myCmpWDegPartial. 980 // 981 // Revision 1.17 2011/03/10 17:25:51 bigatti 982 // -- added CoCoA_ASSERT in myCmpWDegPartial 983 // 984 // Revision 1.16 2011/03/10 16:39:34 abbott 985 // Replaced (very many) size_t by long in function interfaces (for rings, 986 // PPMonoids and modules). Also replaced most size_t inside fn defns. 987 // 988 // Revision 1.15 2009/12/23 18:53:52 abbott 989 // Major change to conversion functions: 990 // convert(..) is now a procedure instead of a function 991 // IsConvertible(..) replaces the former convert(..) function 992 // Added new NumericCast conversion function (placeholder for BOOST feature) 993 // Consequent changes in code which uses these features. 994 // 995 // Revision 1.14 2009/09/22 14:01:33 bigatti 996 // -- added myCmpWDegPartial (ugly name, I know....) 997 // -- cleaned up and realigned code in PPMonoid*.C files 998 // 999 // Revision 1.13 2009/07/24 14:21:42 abbott 1000 // Added an include directive (became necessary after cleaning up other files). 1001 // 1002 // Revision 1.12 2009/03/16 07:28:21 bigatti 1003 // -- fixed a CoCoA_ASSERT on GradingDim 1004 // 1005 // Revision 1.11 2008/05/30 12:44:14 abbott 1006 // Moved "ordering matrices" into their ownn special file. 1007 // 1008 // Revision 1.10 2008/04/21 11:23:11 abbott 1009 // Separated functions dealing with matrices and PPOrderings into a new file. 1010 // Added matrix norms, and completed adjoint. 1011 // 1012 // Revision 1.9 2008/04/18 15:35:57 abbott 1013 // (long overdue) Major revision to matrices 1014 // 1015 // Revision 1.8 2008/04/08 15:26:42 abbott 1016 // Major revision to matrix implementation: added matrix views. 1017 // Lots of changes. 1018 // 1019 // Revision 1.7 2008/03/26 16:52:04 abbott 1020 // Added exponent overflow checks (also for ordvs) when CoCoA_DEBUG is active. 1021 // 1022 // Revision 1.6 2007/12/05 11:06:24 bigatti 1023 // -- changed "size_t StdDeg/myStdDeg(f)" into "long" (and related functions) 1024 // -- changed "log/myLog(f, i)" into "MaxExponent/myMaxExponent(f, i)" 1025 // -- fixed bug in "IsOne(ideal)" in SparsePolyRing.C 1026 // 1027 // Revision 1.5 2007/12/04 14:27:07 bigatti 1028 // -- changed "log(pp, i)" into "exponent(pp, i)" 1029 // 1030 // Revision 1.4 2007/10/30 17:14:07 abbott 1031 // Changed licence from GPL-2 only to GPL-3 or later. 1032 // New version for such an important change. 1033 // 1034 // Revision 1.3 2007/09/25 16:32:30 abbott 1035 // Several minor changes to silence gcc-4.3: 1036 // more #includes, 1037 // and fixed a template problemm in RegisterServerOps.C 1038 // 1039 // Revision 1.2 2007/03/23 18:38:42 abbott 1040 // Separated the "convert" functions (and CheckedCast) into their own files. 1041 // Many consequential changes. Also corrected conversion to doubles. 1042 // 1043 // Revision 1.1.1.1 2007/03/09 15:16:11 abbott 1044 // Imported files 1045 // 1046 // Revision 1.15 2007/03/08 18:22:29 cocoa 1047 // Just whitespace cleaning. 1048 // 1049 // Revision 1.14 2007/03/07 13:44:15 bigatti 1050 // -- minor cleanup 1051 // 1052 // Revision 1.13 2007/03/02 10:47:53 cocoa 1053 // First stage of RingZ modifications -- tests do not compile currently, Anna will fix this. 1054 // 1055 // Revision 1.12 2007/02/10 18:44:03 cocoa 1056 // Added "const" twice to each test and example. 1057 // Eliminated dependency on io.H in several files. 1058 // Improved BuildInfo, and added an example about how to use it. 1059 // Some other minor cleaning. 1060 // 1061 // Revision 1.11 2006/11/27 14:26:44 cocoa 1062 // -- reorganised #include files 1063 // 1064 // Revision 1.10 2006/11/27 13:06:23 cocoa 1065 // Anna and Michael made me check without writing a proper message. 1066 // 1067 // Revision 1.9 2006/11/24 17:12:05 cocoa 1068 // -- reorganized includes of header files 1069 // 1070 // Revision 1.8 2006/11/23 17:33:10 cocoa 1071 // -- changed: OrdvArith::base is now a class (instead of typedef) 1072 // 1073 // Revision 1.7 2006/11/16 11:27:20 cocoa 1074 // -- reinserted myRefCountZero(): sometimes really necessary, in general safe 1075 // 1076 // Revision 1.6 2006/11/14 17:21:44 cocoa 1077 // -- commented out myRefCountZero() (not necessary?) 1078 // 1079 // Revision 1.5 2006/10/16 23:18:59 cocoa 1080 // Corrected use of std::swap and various special swap functions. 1081 // Improved myApply memfn for homs of RingDistrMPolyInlPP. 1082 // 1083 // Revision 1.4 2006/10/06 14:04:15 cocoa 1084 // Corrected position of #ifndef in header files. 1085 // Separated CoCoA_ASSERT into assert.H from config.H; 1086 // many minor consequential changes (have to #include assert.H). 1087 // A little tidying of #include directives (esp. in Max's code). 1088 // 1089 // Revision 1.3 2006/08/07 21:23:25 cocoa 1090 // Removed almost all publicly visible references to SmallExponent_t; 1091 // changed to long in all PPMonoid functions and SparsePolyRing functions. 1092 // DivMask remains to sorted out. 1093 // 1094 // Revision 1.2 2006/06/21 17:07:10 cocoa 1095 // Fixed IsIndet bug -- why are there three almost identical copies of code? 1096 // 1097 // Revision 1.1.1.1 2006/05/30 11:39:37 cocoa 1098 // Imported files 1099 // 1100 // Revision 1.9 2006/05/02 14:40:19 cocoa 1101 // -- Changed "not" into "!" becuase of M$Windoze (by M.Abshoff) 1102 // 1103 // Revision 1.8 2006/04/05 17:26:04 cocoa 1104 // -- added code to deal with ordering matrix with negative entries 1105 // 1106 // Revision 1.7 2006/03/15 18:09:31 cocoa 1107 // Changed names of member functions which print out their object 1108 // into myOutputSelf -- hope this will appease the Intel C++ compiler. 1109 // 1110 // Revision 1.6 2006/03/12 21:28:34 cocoa 1111 // Major check in after many changes 1112 // 1113 // Revision 1.5 2006/03/07 09:55:10 cocoa 1114 // -- changed: OrdvArith::MatrixOrderingMod32749Impl gives NYI error if 1115 // matrix has negative entries 1116 // 1117 // Revision 1.4 2006/02/20 22:41:20 cocoa 1118 // All forms of the log function for power products now return SmallExponent_t 1119 // (instead of int). exponents now resizes the vector rather than requiring 1120 // the user to pass in the correct size. 1121 // 1122 // Revision 1.3 2006/02/15 19:46:41 cocoa 1123 // Corrected check of positivity of input ordering matrix 1124 // (in matrix ordering mod 32749). 1125 // 1126 // Revision 1.2 2005/12/31 12:22:17 cocoa 1127 // Several minor tweaks to silence the Microsoft compiler: 1128 // - added some missing #includes and using directives 1129 // - moved some function defns into the right namespace 1130 // - etc. 1131 // 1132 // Revision 1.1.1.1 2005/10/17 10:46:54 cocoa 1133 // Imported files 1134 // 1135 // Revision 1.6 2005/10/14 15:25:07 cocoa 1136 // Major tidying and cleaning to small prime finite fields. 1137 // Several consequential changes. Improved their documentation. 1138 // 1139 // Added Makefile and script to include/CoCoA/ directory to 1140 // keep library.H up to date. 1141 // 1142 // Revision 1.5 2005/08/08 16:36:32 cocoa 1143 // Just checking in before going on holiday. 1144 // Don't really recall what changes have been made. 1145 // Added IsIndet function for RingElem, PPMonoidElem, 1146 // and a member function of OrdvArith. 1147 // Improved the way failed assertions are handled. 1148 // 1149 // Revision 1.4 2005/07/01 16:08:15 cocoa 1150 // Friday check-in. Major change to structure under PolyRing: 1151 // now SparsePolyRing and DUPolyRing are separated (in preparation 1152 // for implementing iterators). 1153 // 1154 // A number of other relatively minor changes had to be chased through 1155 // (e.g. IndetPower). 1156 // 1157 // Revision 1.3 2005/06/23 15:42:41 cocoa 1158 // Fixed typo in GNU fdl -- all doc/*.txt files affected. 1159 // Minor corrections to PPMonoid (discovered while writing doc). 1160 // 1161 // Revision 1.2 2005/06/22 14:47:56 cocoa 1162 // PPMonoids and PPMonoidElems updated to mirror the structure 1163 // used for rings and RingElems. Many consequential changes. 1164 // 1165 // Revision 1.1.1.1 2005/05/03 15:47:31 cocoa 1166 // Imported files 1167 // 1168 // Revision 1.7 2005/04/20 15:40:48 cocoa 1169 // Major change: modified the standard way errors are to be signalled 1170 // (now via a macro which records filename and line number). Updated 1171 // documentation in error.txt accordingly. 1172 // 1173 // Improved the documentation in matrix.txt (still more work to be done). 1174 // 1175 // Revision 1.6 2005/04/19 14:06:04 cocoa 1176 // Added GPL and GFDL licence stuff. 1177 // 1178 // Revision 1.5 2005/03/11 18:39:36 cocoa 1179 // -- fixed: myCmpDeg 1180 // 1181 // Revision 1.4 2005/03/02 18:46:41 cocoa 1182 // Added new types ConstRefMatrix, and RefMatrix following along 1183 // the lines of ConstRefRingElem and RefRingElem. The semantics 1184 // should be a bit clearer now. 1185 // 1186 // Revision 1.3 2005/02/15 18:19:11 cocoa 1187 // -- fixed base::myCmpDeg (if (ShiftCount==0) return 0;) 1188 // 1189 // Revision 1.2 2005/02/11 14:15:20 cocoa 1190 // New style ring elements and references to ring elements; 1191 // I hope I have finally got it right! 1192 // 1193 // Revision 1.1.1.1 2005/01/27 15:12:13 cocoa 1194 // Imported files 1195 // 1196 // Revision 1.7 2004/11/29 16:22:35 cocoa 1197 // -- added function for computing adjoint and inverse for DenseMatrix 1198 // (so adjoint/inverse matrix is computed by OrdvArith and is no 1199 // longer needed by PPOrdering) 1200 // 1201 // Revision 1.6 2004/11/11 13:38:27 cocoa 1202 // -- change: cout --> GlobalLogput() 1203 // 1204 // Revision 1.5 2004/11/05 16:37:27 cocoa 1205 // -- change: inverse matrix computed modulo 32749 using RingHom 1206 // 1207 // Revision 1.4 2004/11/03 17:50:31 cocoa 1208 // -- added mySetMatrix and mySetInverseMatrixTmp for MatrixOrderingMod32749Impl 1209 // 1210 // Revision 1.3 2004/11/02 15:05:30 cocoa 1211 // -- new: base::myGetExpvBuffer() 1212 // -- new: base::myComputeExpvBuffer 1213 // -- fixed: reference count in destructor 1214 // -- new field: myExpvBuffer 1215 // -- changed: class base is now protected 1216 // 1217 // Revision 1.2 2004/10/29 15:29:30 cocoa 1218 // -- added MatrixOrderingMod32749Impl (not tested) 1219 // 1220 // Revision 1.1 2004/10/21 17:16:37 cocoa 1221 // Fairly major change: new OrdvArith namspace with various members, 1222 // new global typedef SmallExponent_t (defined in config.H). 1223 // 1224