1 /* Copyright (C) 2017 LinBox 2 * 3 * Written by Gavin Harrison, August 2017 4 * 5 * ========LICENCE======== 6 * This file is part of the library LinBox. 7 * 8 * LinBox is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library 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 GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * ========LICENCE======== 22 */ 23 24 #ifndef __LINBOX_polynomial_local_x_H 25 #define __LINBOX_polynomial_local_x_H 26 27 #include "linbox/linbox-config.h" 28 #include "linbox/util/debug.h" 29 30 #include <stdlib.h> 31 #include <algorithm> 32 33 // Namespace in which all LinBox code resides 34 namespace LinBox 35 { 36 template<class Field> 37 class PolynomialLocalX { 38 public: 39 typedef typename Field::Element Polynomial; 40 typedef typename Field::CoeffField CoeffField; 41 typedef typename Field::Coeff Coeff; 42 43 // f(x) * x^e ; x does not divide f(x) 44 typedef struct { 45 size_t e; 46 Polynomial f; 47 } Element; 48 49 // typedef UnparametricRandIter<Element> RandIter; 50 51 // typedef NTL_zz_p CoeffField; 52 // typedef NTL::zz_p Coeff; 53 54 const Field _F; 55 const Element zero, one, mOne, X; 56 size_t exp; 57 PolynomialLocalX(const Field & F,size_t exponent)58 PolynomialLocalX(const Field &F, size_t exponent) : _F(F), 59 zero({0, _F.zero}), one({0, _F.one}), mOne({0, _F.mOne}), 60 X({1, _F.one}), exp(exponent) 61 {} 62 PolynomialLocalX(const PolynomialLocalX & P)63 PolynomialLocalX(const PolynomialLocalX &P) : _F(P._F), zero(P.zero), 64 one(P.one), mOne(P.mOne), X(P.X), exp(P.exp) {} 65 PolynomialLocalX(const PolynomialLocalX & P,size_t exponent)66 PolynomialLocalX(const PolynomialLocalX &P, size_t exponent) : _F(P.F), 67 zero(P.zero), one(P.one), mOne(P.mOne), X(P.X), exp(exponent) {} 68 setExponent(size_t exponent)69 void setExponent(size_t exponent) { 70 exp = exponent; 71 } 72 getExponent()73 size_t getExponent() const { 74 return exp; 75 } 76 getCoeffField()77 const CoeffField &getCoeffField() const { 78 return _F.getCoeffField(); 79 } 80 firstNonZeroCoeff(const Element & a)81 size_t firstNonZeroCoeff(const Element &a) const { 82 return a.e; 83 } 84 normalize(Element & a,const Polynomial & b)85 Element &normalize(Element &a, const Polynomial &b) const { 86 if (_F.isZero(b)) { 87 return a = zero; 88 } 89 90 size_t i = 0; 91 for (; i <= _F.deg(b); i++) { 92 Coeff coeff; 93 if (!getCoeffField().isZero(_F.getCoeff(coeff, b, i))) { 94 break; 95 } 96 } 97 98 Polynomial tmp, x, xe; 99 std::vector<integer> v; 100 _F.init(x, v = {0, 1}); 101 _F.pow(xe, x, i); 102 _F.div(tmp, b, xe); 103 104 return a = { 105 i, 106 tmp 107 }; 108 } 109 normalize(Element & a,const Element & b)110 Element &normalize(Element &a, const Element &b) const { 111 Element tmp; 112 normalize(tmp, b.f); 113 return a = {b.e + tmp.e, tmp.f}; 114 } 115 denormalize(Polynomial & a,const Element & b)116 Polynomial &denormalize(Polynomial &a, const Element &b) const { 117 Polynomial tmp, x, xe; 118 std::vector<integer> v; 119 _F.init(x, v = {0, 1}); 120 _F.pow(xe, x, b.e); 121 _F.mul(a, b.f, xe); 122 123 return a; 124 } 125 assign(Element & a,const Element & b)126 Element &assign(Element &a, const Element &b) const { 127 Polynomial tmp; 128 _F.assign(tmp, b.f); 129 return a = {b.e, tmp}; 130 } 131 init(Element & p)132 Element &init(Element &p) const { 133 return assign(p, zero); 134 } 135 init(Element & p,const std::vector<integer> & v)136 Element &init(Element &p, const std::vector<integer> &v) const { 137 Polynomial tmp; 138 _F.init(tmp, v); 139 return normalize(p, tmp); 140 } 141 init(Element & a,const Polynomial & b)142 Element &init(Element &a, const Polynomial &b) const { 143 return normalize(a, b); 144 } 145 convert(integer & a,const Element & b)146 integer &convert(integer &a, const Element &b) const { 147 Polynomial tmp; 148 return _F.convert(a, denormalize(tmp, b)); 149 } 150 write(std::ostream & os)151 std::ostream& write(std::ostream& os) const { 152 os << "Polynomial local ring at X^" << exp << " using "; 153 _F.write(os); 154 return os; 155 } 156 write(std::ostream & os,const Element & p)157 std::ostream& write(std::ostream& os, const Element &p) const { 158 Polynomial tmp; 159 _F.write(os, denormalize(tmp, p)); 160 return os; 161 } 162 writeNormalized(std::ostream & os,const Element & p)163 std::ostream& writeNormalized(std::ostream& os, const Element &p) const { 164 if (p.e == 0) { 165 _F.write(os, p.f); 166 return os; 167 } 168 169 os << "x"; 170 if (p.e > 1) { 171 os << "^" << p.e; 172 } 173 174 if (_F.isOne(p.f)) { 175 return os; 176 } 177 178 _F.write(os << "*(", p.f) << ")"; 179 return os; 180 } 181 isZero(const Element & a)182 bool isZero(const Element &a) const { 183 return _F.isZero(a.f); 184 } 185 isOne(const Element & a)186 bool isOne(const Element &a) const { 187 return a.e == 0 && _F.isOne(a.f); 188 } 189 isMOne(const Element & a)190 bool isMOne(const Element &a) const { 191 return a.e == 0 && _F.isMOne(a.f); 192 } 193 areEqual(const Element & a,const Element & b)194 bool areEqual(const Element &a, const Element &b) const { 195 return a.e == b.e && _F.areEqual(a.f, b.f); 196 } 197 isUnit(const Element & a)198 bool isUnit(const Element &a) const { 199 return a.e == 0 && !isZero(a); 200 } 201 deg(const Element & p)202 size_t deg(const Element &p) const { 203 return _F.deg(p.f) + p.e; 204 } 205 getCoeff(Coeff & c,const Element & a,size_t e)206 Coeff &getCoeff(Coeff &c, const Element &a, size_t e) const { 207 if (e < a.e) { 208 return getCoeffField().assign(c, getCoeffField().zero); 209 } 210 211 return _F.getCoeff(c, a.f, a.e - e); 212 } 213 leadCoeff(Coeff & c,const Element & a)214 Coeff &leadCoeff(Coeff &c, const Element &a) const { 215 return _F.leadCoeff(c, a.f); 216 } 217 monic(Element & m,const Element & a)218 Element &monic(Element &m, const Element &a) const { 219 Polynomial mf; 220 _F.monic(mf, a.f); 221 222 return m = { 223 a.e, 224 mf 225 }; 226 } 227 228 /// returns true if b divides a evenly isDivisor(const Element & a,const Element & b)229 bool isDivisor(const Element &a, const Element &b) const { 230 return b.e <= a.e && !isZero(b); 231 } 232 233 // b = a * x^e leftShift(Element & b,const Element & a,size_t e)234 Element &leftShift(Element &b, const Element &a, size_t e) const { 235 if (a.e + e > exp) { 236 return b = zero; 237 } 238 239 return b = {a.e + e, a.f}; 240 } 241 242 // b = a / x^e rightShift(Element & b,const Element & a,size_t e)243 Element &rightShift(Element &b, const Element &a, size_t e) const { 244 return b = {a.e - e, a.f}; 245 } 246 rightShiftIn(Element & b,size_t e)247 Element &rightShiftIn(Element &b, size_t e) const { 248 b.e -= e; 249 return b; 250 } 251 div(Element & q,const Element & a,const Element & b)252 Element &div(Element &q, const Element &a, const Element &b) const { 253 if (isZero(a)) { 254 return q = zero; 255 } 256 257 if (_F.isOne(b.f)) { 258 return q = {a.e - b.e, a.f}; 259 } 260 261 Polynomial tmp, x, xe, xer; 262 std::vector<integer> v = {0, 1}; 263 _F.init(x, v); 264 _F.pow(xe, x, exp - a.e + b.e); 265 _F.pow(xer, x, exp - a.e + b.e); 266 267 _F.invMod(tmp, b.f, xe); 268 _F.mulin(tmp, a.f); 269 _F.modin(tmp, xer); 270 271 return q = {a.e - b.e, tmp}; 272 } 273 divin(Element & a,const Element & b)274 Element &divin(Element &a, const Element &b) const { 275 Element tmp; 276 assign(tmp, a); 277 return div(a, tmp, b); 278 } 279 mul(Element & c,const Element & a,const Element & b)280 Element &mul(Element &c, const Element &a, const Element &b) const { 281 if (isZero(a) || isZero(b)) { 282 return c = zero; 283 } 284 285 if (_F.isOne(a.f)) { 286 return c = {a.e + b.e, b.f}; 287 } 288 if (_F.isOne(b.f)) { 289 return c = {a.e + b.e, a.f}; 290 } 291 292 Polynomial tmp, x, xe; 293 std::vector<integer> v = {0, 1}; 294 _F.init(x, v); 295 _F.pow(xe, x, exp - a.e - b.e); 296 _F.mul(tmp, a.f, b.f); 297 _F.modin(tmp, xe); 298 299 return c = {a.e + b.e, tmp}; 300 } 301 mulin(Element & a,const Element & b)302 Element &mulin(Element &a, const Element &b) const { 303 Element tmp; 304 assign(tmp, a); 305 return mul(a, b, tmp); 306 } 307 pow(Element & r,const Element & a,size_t e)308 Element &pow(Element &r, const Element &a, size_t e) { 309 if (a.e * e >= exp) { 310 return r = zero; 311 } 312 313 Polynomial tmp; 314 _F.pow(tmp, a.f, e); 315 return r = { 316 a.e * e, 317 tmp 318 }; 319 } 320 add(Element & c,const Element & a,const Element & b)321 Element &add(Element &c, const Element &a, const Element &b) const { 322 if (a.e > b.e) { 323 return add(c, b, a); 324 } 325 326 if (a.e == b.e) { 327 Polynomial tmp; 328 _F.add(tmp, a.f, b.f); 329 return normalize(c, {a.e, tmp}); 330 } 331 332 Polynomial tmp, x, xe; 333 std::vector<integer> v = {0, 1}; 334 _F.init(x, v); 335 _F.pow(xe, x, b.e - a.e); 336 _F.mul(tmp, xe, b.f); 337 _F.addin(tmp, a.f); 338 return normalize(c, {a.e, tmp}); 339 } 340 addin(Element & a,const Element & b)341 Element &addin(Element &a, const Element &b) const { 342 Element tmp; 343 assign(tmp, a); 344 return add(a, b, tmp); 345 } 346 neg(Element & a,const Element & b)347 Element &neg(Element &a, const Element &b) const { 348 Polynomial tmp; 349 _F.neg(tmp, b.f); 350 return a = {b.e, tmp}; 351 } 352 negin(Element & a)353 Element &negin(Element &a) const { 354 Element tmp; 355 assign(tmp, a); 356 return neg(a, tmp); 357 } 358 359 // r = a*x + y axpy(Element & r,const Element & a,const Element & x,const Element & y)360 Element &axpy(Element &r, const Element &a, const Element &x, const Element &y) const { 361 mul(r, a, x); 362 return addin(r, y); 363 } 364 365 // r += a * x axpyin(Element & r,const Element & a,const Element & x)366 Element &axpyin(Element &r, const Element &a, const Element &x) const { 367 Element tmp; 368 assign(tmp, r); 369 370 return axpy(r, a, x, tmp); 371 } 372 inv(Element & r,const Element & a)373 Element &inv(Element &r, const Element &a) { 374 assert(isUnit(a)); 375 376 Polynomial x, xe; 377 std::vector<integer> v = {0, 1}; 378 _F.init(x, v); 379 _F.pow(xe, x, exp); 380 381 Polynomial tmp; 382 _F.invMod(tmp, a.f, xe); 383 384 return normalize(r, tmp); 385 } 386 }; // end of class PolynomialLocalX 387 388 template<> 389 class PolynomialLocalX<NTL_zz_pX> { 390 public: 391 typedef NTL_zz_pX Field; 392 393 typedef typename Field::Element Polynomial; 394 typedef typename Field::CoeffField CoeffField; 395 typedef typename Field::Coeff Coeff; 396 397 // f(x) * x^e ; x does not divide f(x) 398 typedef typename Field::Element Element; 399 400 // typedef UnparametricRandIter<Element> RandIter; 401 402 const Field _F; 403 const Element zero, one, mOne; 404 size_t exp; 405 PolynomialLocalX(const Field & F,size_t exponent)406 PolynomialLocalX(const Field &F, size_t exponent) : _F(F), 407 zero(_F.zero), one(_F.one), mOne(_F.mOne), exp(exponent) 408 {} 409 PolynomialLocalX(const PolynomialLocalX & P)410 PolynomialLocalX(const PolynomialLocalX &P) : _F(P._F), zero(P.zero), 411 one(P.one), mOne(P.mOne), exp(P.exp) {} 412 setExponent(size_t exponent)413 void setExponent(size_t exponent) { 414 exp = exponent; 415 } 416 getExponent()417 size_t getExponent() const { 418 return exp; 419 } 420 getCoeffField()421 const CoeffField &getCoeffField() const { 422 return _F.getCoeffField(); 423 } 424 firstNonZeroCoeff(const Element & a)425 size_t firstNonZeroCoeff(const Element &a) const { 426 size_t i = 0; 427 for (; i <= _F.deg(a) && NTL::coeff(a, i) == 0; i++); 428 return i; 429 } 430 assign(Element & a,const Element & b)431 Element &assign(Element &a, const Element &b) const { 432 return _F.assign(a, b); 433 } 434 normalize(Element & a,const Polynomial & b)435 Element &normalize(Element &a, const Polynomial &b) const { 436 return assign(a, b); 437 } 438 denormalize(Polynomial & a,const Element & b)439 Polynomial &denormalize(Polynomial &a, const Element &b) const { 440 return assign(a, b); 441 } 442 init(Element & p)443 Element &init(Element &p) const { 444 return assign(p, zero); 445 } 446 init(Element & p,const std::vector<integer> & v)447 Element &init(Element &p, const std::vector<integer> &v) const { 448 return _F.init(p, v); 449 } 450 init(Element & a,const Polynomial & b)451 Element &init(Element &a, const Polynomial &b) const { 452 return assign(a, b); 453 } 454 convert(integer & a,const Element & b)455 integer &convert(integer &a, const Element &b) const { 456 return _F.convert(a, b); 457 } 458 write(std::ostream & os)459 std::ostream& write(std::ostream& os) const { 460 os << "Polynomial local ring at X^" << exp << " using "; 461 _F.write(os); 462 return os; 463 } 464 write(std::ostream & os,const Element & p)465 std::ostream& write(std::ostream& os, const Element &p) const { 466 Polynomial tmp; 467 _F.write(os, denormalize(tmp, p)); 468 return os; 469 } 470 writeNormalized(std::ostream & os,const Element & p)471 std::ostream& writeNormalized(std::ostream& os, const Element &p) const { 472 return write(os, p); 473 } 474 isZero(const Element & a)475 bool isZero(const Element &a) const { 476 return _F.isZero(a); 477 } 478 isOne(const Element & a)479 bool isOne(const Element &a) const { 480 return _F.isOne(a); 481 } 482 isMOne(const Element & a)483 bool isMOne(const Element &a) const { 484 return _F.isMOne(a); 485 } 486 areEqual(const Element & a,const Element & b)487 bool areEqual(const Element &a, const Element &b) const { 488 return _F.areEqual(a, b); 489 } 490 isUnit(const Element & a)491 bool isUnit(const Element &a) const { 492 Coeff coeff; 493 return _F.getCoeff(coeff, a, 0) != 0; 494 } 495 deg(const Element & p)496 size_t deg(const Element &p) const { 497 return _F.deg(p); 498 } 499 getCoeff(Coeff & c,const Element & a,size_t e)500 Coeff &getCoeff(Coeff &c, const Element &a, size_t e) const { 501 return _F.getCoeff(c, a, e); 502 } 503 leadCoeff(Coeff & c,const Element & a)504 Coeff &leadCoeff(Coeff &c, const Element &a) const { 505 return _F.leadCoeff(c, a); 506 } 507 monic(Element & m,const Element & a)508 Element &monic(Element &m, const Element &a) const { 509 return _F.monic(m, a); 510 } 511 512 /// returns true if b divides a evenly isDivisor(const Element & a,const Element & b)513 bool isDivisor(const Element &a, const Element &b) const { 514 if (isZero(b)) { 515 return false; 516 } 517 518 if (isZero(a)) { 519 return true; 520 } 521 522 return firstNonZeroCoeff(a) >= firstNonZeroCoeff(b); 523 } 524 525 // b = a * x^e leftShift(Element & b,const Element & a,size_t e)526 Element &leftShift(Element &b, const Element &a, size_t e) const { 527 if (firstNonZeroCoeff(a) + e >= exp) { 528 return b = zero; 529 } 530 531 return b = NTL::trunc(a << e, exp); 532 } 533 leftShiftIn(Element & b,size_t e)534 Element &leftShiftIn(Element &b, size_t e) const { 535 if (firstNonZeroCoeff(b) + e >= exp) { 536 return b = zero; 537 } 538 539 return b = NTL::trunc(b << e, exp); 540 } 541 542 // b = a / x^e rightShift(Element & b,const Element & a,size_t e)543 Element &rightShift(Element &b, const Element &a, size_t e) const { 544 return b = a >> e; 545 } 546 rightShiftIn(Element & b,size_t e)547 Element &rightShiftIn(Element &b, size_t e) const { 548 return b = b >> e; 549 } 550 mul(Element & c,const Element & a,const Element & b)551 Element &mul(Element &c, const Element &a, const Element &b) const { 552 return c = NTL::MulTrunc(a, b, exp); 553 } 554 mulin(Element & a,const Element & b)555 Element &mulin(Element &a, const Element &b) const { 556 Element tmp; 557 assign(tmp, a); 558 return mul(a, b, tmp); 559 } 560 add(Element & c,const Element & a,const Element & b)561 Element &add(Element &c, const Element &a, const Element &b) const { 562 return _F.add(c, a, b); 563 } 564 addin(Element & a,const Element & b)565 Element &addin(Element &a, const Element &b) const { 566 return _F.addin(a, b); 567 } 568 neg(Element & a,const Element & b)569 Element &neg(Element &a, const Element &b) const { 570 return _F.neg(a, b); 571 } 572 negin(Element & a)573 Element &negin(Element &a) const { 574 return _F.negin(a); 575 } 576 577 // r = a*x + y axpy(Element & r,const Element & a,const Element & x,const Element & y)578 Element &axpy(Element &r, const Element &a, const Element &x, const Element &y) const { 579 mul(r, a, x); 580 return addin(r, y); 581 } 582 583 // r += a * x axpyin(Element & r,const Element & a,const Element & x)584 Element &axpyin(Element &r, const Element &a, const Element &x) const { 585 Element tmp; 586 assign(tmp, r); 587 588 return axpy(r, a, x, tmp); 589 } 590 inv(Element & r,const Element & a)591 Element &inv(Element &r, const Element &a) const { 592 return r = NTL::InvTrunc(a, exp); 593 } 594 }; // end of class PolynomialLocalX<NTL_zz_px> 595 596 template<> 597 class PolynomialLocalX<NTL_zz_pEX> { 598 public: 599 typedef NTL_zz_pEX Field; 600 601 typedef typename Field::Element Polynomial; 602 typedef typename Field::CoeffField CoeffField; 603 typedef typename Field::Coeff Coeff; 604 605 // f(x) * x^e ; x does not divide f(x) 606 typedef typename Field::Element Element; 607 608 // typedef UnparametricRandIter<Element> RandIter; 609 610 const Field _F; 611 const Element zero, one, mOne; 612 size_t exp; 613 PolynomialLocalX(const Field & F,size_t exponent)614 PolynomialLocalX(const Field &F, size_t exponent) : _F(F), 615 zero(_F.zero), one(_F.one), mOne(_F.mOne), exp(exponent) 616 {} 617 PolynomialLocalX(const PolynomialLocalX & P)618 PolynomialLocalX(const PolynomialLocalX &P) : _F(P._F), zero(P.zero), 619 one(P.one), mOne(P.mOne), exp(P.exp) {} 620 setExponent(size_t exponent)621 void setExponent(size_t exponent) { 622 exp = exponent; 623 } 624 getExponent()625 size_t getExponent() const { 626 return exp; 627 } 628 getCoeffField()629 const CoeffField &getCoeffField() const { 630 return _F.getCoeffField(); 631 } 632 firstNonZeroCoeff(const Element & a)633 size_t firstNonZeroCoeff(const Element &a) const { 634 size_t i = 0; 635 for (; i <= _F.deg(a) && NTL::coeff(a, i) == 0; i++); 636 return i; 637 } 638 assign(Element & a,const Element & b)639 Element &assign(Element &a, const Element &b) const { 640 return _F.assign(a, b); 641 } 642 normalize(Element & a,const Polynomial & b)643 Element &normalize(Element &a, const Polynomial &b) const { 644 return assign(a, b); 645 } 646 denormalize(Polynomial & a,const Element & b)647 Polynomial &denormalize(Polynomial &a, const Element &b) const { 648 return assign(a, b); 649 } 650 init(Element & p)651 Element &init(Element &p) const { 652 return assign(p, zero); 653 } 654 init(Element & p,const std::vector<integer> & v)655 Element &init(Element &p, const std::vector<integer> &v) const { 656 return _F.init(p, v); 657 } 658 init(Element & a,const Polynomial & b)659 Element &init(Element &a, const Polynomial &b) const { 660 return assign(a, b); 661 } 662 convert(integer & a,const Element & b)663 integer &convert(integer &a, const Element &b) const { 664 return _F.convert(a, b); 665 } 666 write(std::ostream & os)667 std::ostream& write(std::ostream& os) const { 668 os << "Polynomial local ring at X^" << exp << " using "; 669 _F.write(os); 670 return os; 671 } 672 write(std::ostream & os,const Element & p)673 std::ostream& write(std::ostream& os, const Element &p) const { 674 Polynomial tmp; 675 _F.write(os, denormalize(tmp, p)); 676 return os; 677 } 678 writeNormalized(std::ostream & os,const Element & p)679 std::ostream& writeNormalized(std::ostream& os, const Element &p) const { 680 return write(os, p); 681 } 682 isZero(const Element & a)683 bool isZero(const Element &a) const { 684 return _F.isZero(a); 685 } 686 isOne(const Element & a)687 bool isOne(const Element &a) const { 688 return _F.isOne(a); 689 } 690 isMOne(const Element & a)691 bool isMOne(const Element &a) const { 692 return _F.isMOne(a); 693 } 694 areEqual(const Element & a,const Element & b)695 bool areEqual(const Element &a, const Element &b) const { 696 return _F.areEqual(a, b); 697 } 698 isUnit(const Element & a)699 bool isUnit(const Element &a) const { 700 Coeff coeff; 701 return _F.getCoeff(coeff, a, 0) != 0; 702 } 703 deg(const Element & p)704 size_t deg(const Element &p) const { 705 return _F.deg(p); 706 } 707 getCoeff(Coeff & c,const Element & a,size_t e)708 Coeff &getCoeff(Coeff &c, const Element &a, size_t e) const { 709 return _F.getCoeff(c, a, e); 710 } 711 leadCoeff(Coeff & c,const Element & a)712 Coeff &leadCoeff(Coeff &c, const Element &a) const { 713 return _F.leadCoeff(c, a); 714 } 715 monic(Element & m,const Element & a)716 Element &monic(Element &m, const Element &a) const { 717 return _F.monic(m, a); 718 } 719 720 /// returns true if b divides a evenly isDivisor(const Element & a,const Element & b)721 bool isDivisor(const Element &a, const Element &b) const { 722 if (isZero(b)) { 723 return false; 724 } 725 726 if (isZero(a)) { 727 return true; 728 } 729 730 return firstNonZeroCoeff(a) >= firstNonZeroCoeff(b); 731 } 732 733 // b = a * x^e leftShift(Element & b,const Element & a,size_t e)734 Element &leftShift(Element &b, const Element &a, size_t e) const { 735 if (firstNonZeroCoeff(a) + e >= exp) { 736 return b = zero; 737 } 738 739 return b = NTL::trunc(a << e, exp); 740 } 741 leftShiftIn(Element & b,size_t e)742 Element &leftShiftIn(Element &b, size_t e) const { 743 if (firstNonZeroCoeff(b) + e >= exp) { 744 return b = zero; 745 } 746 747 return b = NTL::trunc(b << e, exp); 748 } 749 750 // b = a / x^e rightShift(Element & b,const Element & a,size_t e)751 Element &rightShift(Element &b, const Element &a, size_t e) const { 752 return b = a >> e; 753 } 754 rightShiftIn(Element & b,size_t e)755 Element &rightShiftIn(Element &b, size_t e) const { 756 return b = b >> e; 757 } 758 mul(Element & c,const Element & a,const Element & b)759 Element &mul(Element &c, const Element &a, const Element &b) const { 760 return c = NTL::MulTrunc(a, b, exp); 761 } 762 mulin(Element & a,const Element & b)763 Element &mulin(Element &a, const Element &b) const { 764 Element tmp; 765 assign(tmp, a); 766 return mul(a, b, tmp); 767 } 768 add(Element & c,const Element & a,const Element & b)769 Element &add(Element &c, const Element &a, const Element &b) const { 770 return _F.add(c, a, b); 771 } 772 addin(Element & a,const Element & b)773 Element &addin(Element &a, const Element &b) const { 774 return _F.addin(a, b); 775 } 776 neg(Element & a,const Element & b)777 Element &neg(Element &a, const Element &b) const { 778 return _F.neg(a, b); 779 } 780 negin(Element & a)781 Element &negin(Element &a) const { 782 return _F.negin(a); 783 } 784 785 // r = a*x + y axpy(Element & r,const Element & a,const Element & x,const Element & y)786 Element &axpy(Element &r, const Element &a, const Element &x, const Element &y) const { 787 mul(r, a, x); 788 return addin(r, y); 789 } 790 791 // r += a * x axpyin(Element & r,const Element & a,const Element & x)792 Element &axpyin(Element &r, const Element &a, const Element &x) const { 793 Element tmp; 794 assign(tmp, r); 795 796 return axpy(r, a, x, tmp); 797 } 798 inv(Element & r,const Element & a)799 Element &inv(Element &r, const Element &a) const { 800 return r = NTL::InvTrunc(a, exp); 801 } 802 }; // end of class PolynomialLocalX<NTL_zz_px> 803 804 template<class PolynomialRing> 805 class Hom<PolynomialRing, PolynomialLocalX<PolynomialRing>> { 806 public: 807 typedef PolynomialRing Source; 808 typedef PolynomialLocalX<PolynomialRing> Target; 809 typedef typename Source::Element SrcElt; 810 typedef typename Target::Element Elt; 811 812 public: Hom(const Source & S,const Target & T)813 Hom(const Source& S, const Target& T) : _source(S), _target(T) {} 814 image(Elt & t,const SrcElt & s)815 Elt& image(Elt& t, const SrcElt& s) { 816 return _target.init(t, s); 817 } 818 preimage(SrcElt & s,const Elt & t)819 SrcElt& preimage(SrcElt& s, const Elt& t) { 820 return _target.convert(s, t); 821 } 822 source()823 const Source& source() { return _source;} target()824 const Target& target() { return _target;} 825 826 private: 827 const Source& _source; 828 const Target& _target; 829 }; // end Hom<PolynomialRing, PolynomialLocalX> 830 } // end of namespace LinBox 831 832 #endif // __LINBOX_polynomial_local_x_H 833 834 835 // vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,:0,t0,+0,=s 836 // Local Variables: 837 // mode: C++ 838 // tab-width: 8 839 // indent-tabs-mode: nil 840 // c-basic-offset: 8 841 // End: 842 843