001/* 002 * $Id$ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.Collection; 010import java.util.List; 011import java.util.Map; 012import java.util.SortedMap; 013import java.util.TreeMap; 014 015import org.apache.logging.log4j.LogManager; 016import org.apache.logging.log4j.Logger; 017 018import edu.jas.arith.BigInteger; 019import edu.jas.arith.BigRational; 020import edu.jas.poly.AlgebraicNumber; 021import edu.jas.poly.AlgebraicNumberRing; 022import edu.jas.poly.ExpVector; 023import edu.jas.poly.GenPolynomial; 024import edu.jas.poly.GenPolynomialRing; 025import edu.jas.poly.PolyUtil; 026import edu.jas.poly.TermOrderByName; 027import edu.jas.structure.GcdRingElem; 028import edu.jas.structure.RingElem; 029import edu.jas.structure.RingFactory; 030import edu.jas.structure.UnaryFunctor; 031import edu.jas.util.ListUtil; 032 033 034/** 035 * Polynomial ufd utilities. For example conversion between different 036 * representations and Kronecker substitution. 037 * @author Heinz Kredel 038 */ 039 040public class PolyUfdUtil { 041 042 043 private static final Logger logger = LogManager.getLogger(PolyUfdUtil.class); 044 045 046 private static final boolean debug = logger.isDebugEnabled(); 047 048 049 /** 050 * Factors of Quotient rational function. 051 * @param A rational function to be factored. 052 * @return list of irreducible rational function parts. 053 */ 054 public static <C extends GcdRingElem<C>> SortedMap<Quotient<C>, Long> factors(Quotient<C> A) { 055 SortedMap<Quotient<C>, Long> factors = new TreeMap<Quotient<C>, Long>(); 056 if (A == null || A.isZERO()) { 057 return factors; 058 } 059 if (A.abs().isONE()) { 060 factors.put(A, 1L); 061 return factors; 062 } 063 QuotientRing<C> qfac = A.ring; 064 GenPolynomialRing<C> fac = qfac.ring; 065 FactorAbstract<C> eng = FactorFactory.<C> getImplementation(fac.coFac); 066 GenPolynomial<C> n = A.num; 067 SortedMap<GenPolynomial<C>, Long> numfactors = eng.factors(n); 068 for (Map.Entry<GenPolynomial<C>, Long> me : numfactors.entrySet()) { 069 GenPolynomial<C> f = me.getKey(); 070 Long e = me.getValue(); 071 Quotient<C> q = new Quotient<C>(qfac, f); 072 factors.put(q, e); 073 } 074 GenPolynomial<C> d = A.den; 075 if (d.isONE()) { 076 return factors; 077 } 078 GenPolynomial<C> one = fac.getONE(); 079 SortedMap<GenPolynomial<C>, Long> denfactors = eng.factors(d); 080 for (Map.Entry<GenPolynomial<C>, Long> me : denfactors.entrySet()) { 081 GenPolynomial<C> f = me.getKey(); 082 Long e = me.getValue(); 083 Quotient<C> q = new Quotient<C>(qfac, one, f); 084 factors.put(q, e); 085 } 086 return factors; 087 } 088 089 090 /** 091 * Quotient is (squarefree) factorization. 092 * @param P Quotient. 093 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 094 * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. 095 */ 096 public static <C extends GcdRingElem<C>> boolean isFactorization(Quotient<C> P, 097 SortedMap<Quotient<C>, Long> F) { 098 if (P == null || F == null) { 099 throw new IllegalArgumentException("P and F may not be null"); 100 } 101 if (P.isZERO() && F.size() == 0) { 102 return true; 103 } 104 Quotient<C> t = P.ring.getONE(); 105 for (Map.Entry<Quotient<C>, Long> me : F.entrySet()) { 106 Quotient<C> f = me.getKey(); 107 Long E = me.getValue(); 108 long e = E.longValue(); 109 Quotient<C> g = f.power(e); 110 t = t.multiply(g); 111 } 112 boolean f = P.equals(t) || P.equals(t.negate()); 113 if (!f) { 114 P = P.monic(); 115 t = t.monic(); 116 f = P.equals(t) || P.equals(t.negate()); 117 if (f) { 118 return f; 119 } 120 logger.info("no factorization(map): F = " + F + ", P = " + P + ", t = " + t); 121 } 122 return f; 123 } 124 125 126 /** 127 * Integral polynomial from rational function coefficients. Represent as 128 * polynomial with integral polynomial coefficients by multiplication with 129 * the lcm of the numerators of the rational function coefficients. 130 * @param fac result polynomial factory. 131 * @param A polynomial with rational function coefficients to be converted. 132 * @return polynomial with integral polynomial coefficients. 133 */ 134 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> integralFromQuotientCoefficients( 135 GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<Quotient<C>> A) { 136 GenPolynomial<GenPolynomial<C>> B = fac.getZERO().copy(); 137 if (A == null || A.isZERO()) { 138 return B; 139 } 140 GenPolynomial<C> c = null; 141 GenPolynomial<C> d; 142 GenPolynomial<C> x; 143 GreatestCommonDivisor<C> ufd = new GreatestCommonDivisorSubres<C>(); 144 int s = 0; 145 // lcm of denominators 146 for (Quotient<C> y : A.getMap().values()) { 147 x = y.den; 148 // c = lcm(c,x) 149 if (c == null) { 150 c = x; 151 s = x.signum(); 152 } else { 153 d = ufd.gcd(c, x); 154 c = c.multiply(x.divide(d)); 155 } 156 } 157 if (s < 0) { 158 c = c.negate(); 159 } 160 for (Map.Entry<ExpVector, Quotient<C>> y : A.getMap().entrySet()) { 161 ExpVector e = y.getKey(); 162 Quotient<C> a = y.getValue(); 163 // p = n*(c/d) 164 GenPolynomial<C> b = c.divide(a.den); 165 GenPolynomial<C> p = a.num.multiply(b); 166 //B = B.sum( p, e ); // inefficient 167 B.doPutToMap(e, p); 168 } 169 return B; 170 } 171 172 173 /** 174 * Integral polynomial from rational function coefficients. Represent as 175 * polynomial with integral polynomial coefficients by multiplication with 176 * the lcm of the numerators of the rational function coefficients. 177 * @param fac result polynomial factory. 178 * @param L list of polynomial with rational function coefficients to be 179 * converted. 180 * @return list of polynomials with integral polynomial coefficients. 181 */ 182 public static <C extends GcdRingElem<C>> List<GenPolynomial<GenPolynomial<C>>> integralFromQuotientCoefficients( 183 GenPolynomialRing<GenPolynomial<C>> fac, Collection<GenPolynomial<Quotient<C>>> L) { 184 if (L == null) { 185 return null; 186 } 187 List<GenPolynomial<GenPolynomial<C>>> list = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size()); 188 for (GenPolynomial<Quotient<C>> p : L) { 189 list.add(integralFromQuotientCoefficients(fac, p)); 190 } 191 return list; 192 } 193 194 195 /** 196 * Rational function from integral polynomial coefficients. Represent as 197 * polynomial with type Quotient<C> coefficients. 198 * @param fac result polynomial factory. 199 * @param A polynomial with integral polynomial coefficients to be 200 * converted. 201 * @return polynomial with type Quotient<C> coefficients. 202 */ 203 public static <C extends GcdRingElem<C>> GenPolynomial<Quotient<C>> quotientFromIntegralCoefficients( 204 GenPolynomialRing<Quotient<C>> fac, GenPolynomial<GenPolynomial<C>> A) { 205 GenPolynomial<Quotient<C>> B = fac.getZERO().copy(); 206 if (A == null || A.isZERO()) { 207 return B; 208 } 209 RingFactory<Quotient<C>> cfac = fac.coFac; 210 QuotientRing<C> qfac = (QuotientRing<C>) cfac; 211 for (Map.Entry<ExpVector, GenPolynomial<C>> y : A.getMap().entrySet()) { 212 ExpVector e = y.getKey(); 213 GenPolynomial<C> a = y.getValue(); 214 Quotient<C> p = new Quotient<C>(qfac, a); // can not be zero 215 if (!p.isZERO()) { 216 //B = B.sum( p, e ); // inefficient 217 B.doPutToMap(e, p); 218 } 219 } 220 return B; 221 } 222 223 224 /** 225 * Rational function from integral polynomial coefficients. Represent as 226 * polynomial with type Quotient<C> coefficients. 227 * @param fac result polynomial factory. 228 * @param L list of polynomials with integral polynomial coefficients to be 229 * converted. 230 * @return list of polynomials with type Quotient<C> coefficients. 231 */ 232 public static <C extends GcdRingElem<C>> List<GenPolynomial<Quotient<C>>> quotientFromIntegralCoefficients( 233 GenPolynomialRing<Quotient<C>> fac, Collection<GenPolynomial<GenPolynomial<C>>> L) { 234 if (L == null) { 235 return null; 236 } 237 List<GenPolynomial<Quotient<C>>> list = new ArrayList<GenPolynomial<Quotient<C>>>(L.size()); 238 for (GenPolynomial<GenPolynomial<C>> p : L) { 239 list.add(quotientFromIntegralCoefficients(fac, p)); 240 } 241 return list; 242 } 243 244 245 /** 246 * From BigInteger coefficients. Represent as polynomial with type 247 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 248 * @param fac result polynomial factory. 249 * @param A polynomial with GenPolynomial<BigInteger> coefficients to 250 * be converted. 251 * @return polynomial with type GenPolynomial<C> coefficients. 252 */ 253 public static <C extends RingElem<C>> GenPolynomial<GenPolynomial<C>> fromIntegerCoefficients( 254 GenPolynomialRing<GenPolynomial<C>> fac, GenPolynomial<GenPolynomial<BigInteger>> A) { 255 GenPolynomial<GenPolynomial<C>> B = fac.getZERO().copy(); 256 if (A == null || A.isZERO()) { 257 return B; 258 } 259 RingFactory<GenPolynomial<C>> cfac = fac.coFac; 260 GenPolynomialRing<C> rfac = (GenPolynomialRing<C>) cfac; 261 for (Map.Entry<ExpVector, GenPolynomial<BigInteger>> y : A.getMap().entrySet()) { 262 ExpVector e = y.getKey(); 263 GenPolynomial<BigInteger> a = y.getValue(); 264 GenPolynomial<C> p = PolyUtil.<C> fromIntegerCoefficients(rfac, a); 265 if (!p.isZERO()) { 266 //B = B.sum( p, e ); // inefficient 267 B.doPutToMap(e, p); 268 } 269 } 270 return B; 271 } 272 273 274 /** 275 * From BigInteger coefficients. Represent as polynomial with type 276 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 277 * @param fac result polynomial factory. 278 * @param L polynomial list with GenPolynomial<BigInteger> 279 * coefficients to be converted. 280 * @return polynomial list with polynomials with type GenPolynomial<C> 281 * coefficients. 282 */ 283 public static <C extends RingElem<C>> List<GenPolynomial<GenPolynomial<C>>> fromIntegerCoefficients( 284 GenPolynomialRing<GenPolynomial<C>> fac, 285 List<GenPolynomial<GenPolynomial<BigInteger>>> L) { 286 List<GenPolynomial<GenPolynomial<C>>> K = null; 287 if (L == null) { 288 return K; 289 } 290 K = new ArrayList<GenPolynomial<GenPolynomial<C>>>(L.size()); 291 if (L.size() == 0) { 292 return K; 293 } 294 for (GenPolynomial<GenPolynomial<BigInteger>> a : L) { 295 GenPolynomial<GenPolynomial<C>> b = fromIntegerCoefficients(fac, a); 296 K.add(b); 297 } 298 return K; 299 } 300 301 302 //------------------------------ 303 304 /** 305 * BigInteger from BigRational coefficients. Represent as polynomial with 306 * type GenPolynomial<BigInteger> coefficients. 307 * @param fac result polynomial factory. 308 * @param A polynomial with GenPolynomial<BigRational> coefficients to 309 * be converted. 310 * @return polynomial with type GenPolynomial<BigInteger> 311 * coefficients. 312 */ 313 public static GenPolynomial<GenPolynomial<BigInteger>> integerFromRationalCoefficients( 314 GenPolynomialRing<GenPolynomial<BigInteger>> fac, 315 GenPolynomial<GenPolynomial<BigRational>> A) { 316 GenPolynomial<GenPolynomial<BigInteger>> B = fac.getZERO().copy(); 317 if (A == null || A.isZERO()) { 318 return B; 319 } 320 java.math.BigInteger gcd = null; 321 java.math.BigInteger lcm = null; 322 int sLCM = 0; 323 int sGCD = 0; 324 // lcm of all denominators 325 for (GenPolynomial<BigRational> av : A.getMap().values()) { 326 for (BigRational y : av.getMap().values()) { 327 java.math.BigInteger numerator = y.numerator(); 328 java.math.BigInteger denominator = y.denominator(); 329 // lcm = lcm(lcm,x) 330 if (lcm == null) { 331 lcm = denominator; 332 sLCM = denominator.signum(); 333 } else { 334 java.math.BigInteger d = lcm.gcd(denominator); 335 lcm = lcm.multiply(denominator.divide(d)); 336 } 337 // gcd = gcd(gcd,x) 338 if (gcd == null) { 339 gcd = numerator; 340 sGCD = numerator.signum(); 341 } else { 342 gcd = gcd.gcd(numerator); 343 } 344 } 345 //System.out.println("gcd = " + gcd + ", lcm = " + lcm); 346 } 347 if (sLCM < 0) { 348 lcm = lcm.negate(); 349 } 350 if (sGCD < 0) { 351 gcd = gcd.negate(); 352 } 353 //System.out.println("gcd** = " + gcd + ", lcm = " + lcm); 354 RingFactory<GenPolynomial<BigInteger>> cfac = fac.coFac; 355 GenPolynomialRing<BigInteger> rfac = (GenPolynomialRing<BigInteger>) cfac; 356 for (Map.Entry<ExpVector, GenPolynomial<BigRational>> y : A.getMap().entrySet()) { 357 ExpVector e = y.getKey(); 358 GenPolynomial<BigRational> a = y.getValue(); 359 // common denominator over all coefficients 360 GenPolynomial<BigInteger> p = PolyUtil.integerFromRationalCoefficients(rfac, gcd, lcm, a); 361 if (!p.isZERO()) { 362 //B = B.sum( p, e ); // inefficient 363 B.doPutToMap(e, p); 364 } 365 } 366 return B; 367 } 368 369 370 /** 371 * BigInteger from BigRational coefficients. Represent as polynomial with 372 * type GenPolynomial<BigInteger> coefficients. 373 * @param fac result polynomial factory. 374 * @param L polynomial list with GenPolynomial<BigRational> 375 * coefficients to be converted. 376 * @return polynomial list with polynomials with type 377 * GenPolynomial<BigInteger> coefficients. 378 */ 379 public static List<GenPolynomial<GenPolynomial<BigInteger>>> integerFromRationalCoefficients( 380 GenPolynomialRing<GenPolynomial<BigInteger>> fac, 381 List<GenPolynomial<GenPolynomial<BigRational>>> L) { 382 List<GenPolynomial<GenPolynomial<BigInteger>>> K = null; 383 if (L == null) { 384 return K; 385 } 386 K = new ArrayList<GenPolynomial<GenPolynomial<BigInteger>>>(L.size()); 387 if (L.isEmpty()) { 388 return K; 389 } 390 for (GenPolynomial<GenPolynomial<BigRational>> a : L) { 391 GenPolynomial<GenPolynomial<BigInteger>> b = integerFromRationalCoefficients(fac, a); 392 K.add(b); 393 } 394 return K; 395 } 396 397 398 /** 399 * Introduce lower variable. Represent as polynomial with type 400 * GenPolynomial<C> coefficients. 401 * @param rfac result polynomial factory. 402 * @param A polynomial to be extended. 403 * @return polynomial with type GenPolynomial<C> coefficients. 404 */ 405 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> introduceLowerVariable( 406 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<C> A) { 407 if (A == null || rfac == null) { 408 return null; 409 } 410 GenPolynomial<GenPolynomial<C>> Pc = rfac.getONE().multiply(A); 411 if (Pc.isZERO()) { 412 return Pc; 413 } 414 Pc = PolyUtil.<C> switchVariables(Pc); 415 return Pc; 416 } 417 418 419 /** 420 * From AlgebraicNumber coefficients. Represent as polynomial with type 421 * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. 422 * @param rfac result polynomial factory. 423 * @param A polynomial with AlgebraicNumber coefficients to be converted. 424 * @param k for (y-k x) substitution. 425 * @return polynomial with type GenPolynomial<C> coefficients. 426 */ 427 public static <C extends GcdRingElem<C>> GenPolynomial<GenPolynomial<C>> substituteFromAlgebraicCoefficients( 428 GenPolynomialRing<GenPolynomial<C>> rfac, GenPolynomial<AlgebraicNumber<C>> A, long k) { 429 if (A == null || rfac == null) { 430 return null; 431 } 432 if (A.isZERO()) { 433 return rfac.getZERO(); 434 } 435 // setup x - k alpha 436 GenPolynomialRing<AlgebraicNumber<C>> apfac = A.ring; 437 GenPolynomial<AlgebraicNumber<C>> x = apfac.univariate(0); 438 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) A.ring.coFac; 439 AlgebraicNumber<C> alpha = afac.getGenerator(); 440 AlgebraicNumber<C> ka = afac.fromInteger(k); 441 GenPolynomial<AlgebraicNumber<C>> s = x.subtract(ka.multiply(alpha)); // x - k alpha 442 //System.out.println("x - k alpha = " + s); 443 //System.out.println("s.ring = " + s.ring.toScript()); 444 if (debug) { 445 logger.info("x - k alpha: " + s); 446 } 447 // substitute, convert and switch 448 //System.out.println("Asubs = " + A); 449 GenPolynomial<AlgebraicNumber<C>> B; 450 if (s.ring.nvar <= 1) { 451 B = PolyUtil.<AlgebraicNumber<C>> substituteMain(A, s); 452 } else { 453 B = PolyUtil.<AlgebraicNumber<C>> substituteUnivariateMult(A, s); 454 } 455 //System.out.println("Bsubs = " + B); 456 GenPolynomial<GenPolynomial<C>> Pc = PolyUtil.<C> fromAlgebraicCoefficients(rfac, B); // Q[alpha][x] 457 //System.out.println("Pc[a,x] = " + Pc); 458 Pc = PolyUtil.<C> switchVariables(Pc); // Q[x][alpha] 459 //System.out.println("Pc[x,a] = " + Pc); 460 return Pc; 461 } 462 463 464 /** 465 * Convert to AlgebraicNumber coefficients. Represent as polynomial with 466 * AlgebraicNumber<C> coefficients, C is e.g. ModInteger or BigRational. 467 * @param pfac result polynomial factory. 468 * @param A polynomial with GenPolynomial<BigInteger> coefficients to 469 * be converted. 470 * @param k for (y-k x) substitution. 471 * @return polynomial with AlgebraicNumber<C> coefficients. 472 */ 473 public static <C extends GcdRingElem<C>> GenPolynomial<AlgebraicNumber<C>> substituteConvertToAlgebraicCoefficients( 474 GenPolynomialRing<AlgebraicNumber<C>> pfac, GenPolynomial<C> A, long k) { 475 if (A == null || pfac == null) { 476 return null; 477 } 478 if (A.isZERO()) { 479 return pfac.getZERO(); 480 } 481 // convert to Q(alpha)[x] 482 GenPolynomial<AlgebraicNumber<C>> B = PolyUtil.<C> convertToAlgebraicCoefficients(pfac, A); 483 // setup x .+. k alpha for back substitution 484 GenPolynomial<AlgebraicNumber<C>> x = pfac.univariate(0); 485 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 486 AlgebraicNumber<C> alpha = afac.getGenerator(); 487 AlgebraicNumber<C> ka = afac.fromInteger(k); 488 GenPolynomial<AlgebraicNumber<C>> s = x.sum(ka.multiply(alpha)); // x + k alpha 489 // substitute 490 //System.out.println("s.ring = " + s.ring.toScript()); 491 GenPolynomial<AlgebraicNumber<C>> N; 492 if (s.ring.nvar <= 1) { 493 N = PolyUtil.<AlgebraicNumber<C>> substituteMain(B, s); 494 } else { 495 N = PolyUtil.<AlgebraicNumber<C>> substituteUnivariateMult(B, s); 496 } 497 return N; 498 } 499 500 501 /** 502 * Norm of a polynomial with AlgebraicNumber coefficients. 503 * @param A uni or multivariate polynomial from 504 * GenPolynomial<AlgebraicNumber<C>>. 505 * @param k for (y - k x) substitution. 506 * @return norm(A) = res_x(A(x,y),m(x)) in GenPolynomialRing<C>. 507 */ 508 public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A, 509 long k) { 510 if (A == null) { 511 return null; 512 } 513 GenPolynomialRing<AlgebraicNumber<C>> pfac = A.ring; // Q(alpha)[x] 514 //if (pfac.nvar > 1) { 515 // throw new IllegalArgumentException("only for univariate polynomials"); 516 //} 517 AlgebraicNumberRing<C> afac = (AlgebraicNumberRing<C>) pfac.coFac; 518 GenPolynomial<C> agen = afac.modul; 519 GenPolynomialRing<C> cfac = afac.ring; 520 if (A.isZERO()) { 521 return cfac.getZERO(); 522 } 523 AlgebraicNumber<C> ldcf = A.leadingBaseCoefficient(); 524 if (!ldcf.isONE()) { 525 A = A.monic(); 526 } 527 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, pfac); 528 //System.out.println("rfac = " + rfac.toScript()); 529 530 // transform minimal polynomial to bi-variate polynomial 531 GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C> introduceLowerVariable(rfac, agen); 532 533 // transform to bi-variate polynomial, 534 // switching varaible sequence from Q[alpha][x] to Q[X][alpha] 535 GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C> substituteFromAlgebraicCoefficients(rfac, A, k); 536 Pc = PolyUtil.<C> monic(Pc); 537 //System.out.println("Pc = " + Pc.toScript() + " :: " + Pc.ring.toScript()); 538 539 GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>( /*cfac.coFac*/); 540 // = (GreatestCommonDivisorAbstract<C>)GCDFactory.<C>getImplementation( cfac.coFac ); 541 542 GenPolynomial<GenPolynomial<C>> Rc = engine.recursiveUnivariateResultant(Pc, Ac); 543 //System.out.println("Rc = " + Rc.toScript()); 544 GenPolynomial<C> res = Rc.leadingBaseCoefficient(); 545 res = res.monic(); 546 return res; 547 } 548 549 550 /** 551 * Norm of a polynomial with AlgebraicNumber coefficients. 552 * @param A polynomial from GenPolynomial<AlgebraicNumber<C>>. 553 * @return norm(A) = resultant_x( A(x,y), m(x) ) in K[y]. 554 */ 555 public static <C extends GcdRingElem<C>> GenPolynomial<C> norm(GenPolynomial<AlgebraicNumber<C>> A) { 556 return norm(A, 0L); 557 } 558 559 560 /** 561 * Ensure that the field property is determined. Checks if modul is 562 * irreducible and modifies the algebraic number ring. 563 * @param afac algebraic number ring. 564 */ 565 public static <C extends GcdRingElem<C>> void ensureFieldProperty(AlgebraicNumberRing<C> afac) { 566 if (afac.getField() != -1) { 567 return; 568 } 569 if (!afac.ring.coFac.isField()) { 570 afac.setField(false); 571 return; 572 } 573 Factorization<C> mf = FactorFactory.<C> getImplementation(afac.ring); 574 if (mf.isIrreducible(afac.modul)) { 575 afac.setField(true); 576 } else { 577 afac.setField(false); 578 } 579 } 580 581 582 /** 583 * Construct a random irreducible univariate polynomial of degree d. 584 * @param cfac coefficient ring. 585 * @param degree of random polynomial. 586 * @return irreducible univariate polynomial. 587 */ 588 public static <C extends GcdRingElem<C>> GenPolynomial<C> randomIrreduciblePolynomial(RingFactory<C> cfac, 589 int degree) { 590 if (!cfac.isField()) { 591 throw new IllegalArgumentException("coefficient ring must be a field " + cfac); 592 } 593 GenPolynomialRing<C> ring = new GenPolynomialRing<C>(cfac, 1, TermOrderByName.INVLEX); 594 Factorization<C> eng = FactorFactory.<C> getImplementation(ring); 595 GenPolynomial<C> mod = ring.getZERO(); 596 int k = cfac.characteristic().bitLength(); // log 597 if (k < 3) { 598 k = 7; 599 } 600 int l = degree / 2 + 2; 601 int d = degree + 1; 602 float q = 0.55f; 603 for (;;) { 604 mod = ring.random(k, l, d, q).monic(); 605 if (mod.degree() != degree) { 606 mod = mod.sum(ring.univariate(0, degree)); 607 } 608 if (mod.trailingBaseCoefficient().isZERO()) { 609 mod = mod.sum(ring.getONE()); 610 } 611 //System.out.println("algebriacNumberField: mod = " + mod + ", k = " + k); 612 if (eng.isIrreducible(mod)) { 613 break; 614 } 615 } 616 return mod; 617 } 618 619 620 /** 621 * Construct an algebraic number field of degree d. Uses a random 622 * irreducible polynomial of degree d as modulus of the algebraic number 623 * ring. 624 * @param cfac coefficient ring. 625 * @param degree of random polynomial. 626 * @return algebraic number field. 627 */ 628 public static <C extends GcdRingElem<C>> AlgebraicNumberRing<C> algebraicNumberField(RingFactory<C> cfac, 629 int degree) { 630 GenPolynomial<C> mod = randomIrreduciblePolynomial(cfac, degree); 631 AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(mod, true); 632 return afac; 633 } 634 635 636 /** 637 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a 638 * univariate polynomial. 639 * @param A polynomial to be converted. 640 * @return a univariate polynomial. 641 */ 642 public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A) { 643 if (A == null) { 644 return A; 645 } 646 long d = A.degree() + 1L; 647 return substituteKronecker(A, d); 648 } 649 650 651 /** 652 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a 653 * univariate polynomial. 654 * @param A polynomial to be converted. 655 * @return a univariate polynomial. 656 */ 657 public static <C extends GcdRingElem<C>> GenPolynomial<C> substituteKronecker(GenPolynomial<C> A, 658 long d) { 659 if (A == null) { 660 return A; 661 } 662 RingFactory<C> cfac = A.ring.coFac; 663 GenPolynomialRing<C> ufac = new GenPolynomialRing<C>(cfac, 1); 664 GenPolynomial<C> B = ufac.getZERO().copy(); 665 if (A.isZERO()) { 666 return B; 667 } 668 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 669 ExpVector e = y.getKey(); 670 C a = y.getValue(); 671 long f = 0L; 672 long h = 1L; 673 for (int i = 0; i < e.length(); i++) { 674 long j = e.getVal(i) * h; 675 f += j; 676 h *= d; 677 } 678 ExpVector g = ExpVector.create(1, 0, f); 679 B.doPutToMap(g, a); 680 } 681 return B; 682 } 683 684 685 /** 686 * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct 687 * univariate polynomials. 688 * @param A list of polynomials to be converted. 689 * @return a list of univariate polynomials. 690 */ 691 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> substituteKronecker( 692 List<GenPolynomial<C>> A, int d) { 693 if (A == null || A.get(0) == null) { 694 return null; 695 } 696 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new SubstKronecker<C>(d)); 697 } 698 699 700 /** 701 * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct a 702 * multivariate polynomial. 703 * @param A polynomial to be converted. 704 * @param fac result polynomial factory. 705 * @return a multivariate polynomial. 706 */ 707 public static <C extends GcdRingElem<C>> GenPolynomial<C> backSubstituteKronecker( 708 GenPolynomialRing<C> fac, GenPolynomial<C> A, long d) { 709 if (A == null) { 710 return A; 711 } 712 if (fac == null) { 713 throw new IllegalArgumentException("null factory not allowed "); 714 } 715 int n = fac.nvar; 716 GenPolynomial<C> B = fac.getZERO().copy(); 717 if (A.isZERO()) { 718 return B; 719 } 720 for (Map.Entry<ExpVector, C> y : A.getMap().entrySet()) { 721 ExpVector e = y.getKey(); 722 C a = y.getValue(); 723 long f = e.getVal(0); 724 ExpVector g = ExpVector.create(n); 725 for (int i = 0; i < n; i++) { 726 long j = f % d; 727 f /= d; 728 g = g.subst(i, j); 729 } 730 B.doPutToMap(g, a); 731 } 732 return B; 733 } 734 735 736 /** 737 * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct 738 * multivariate polynomials. 739 * @param A list of polynomials to be converted. 740 * @param fac result polynomial factory. 741 * @return a list of multivariate polynomials. 742 */ 743 public static <C extends GcdRingElem<C>> List<GenPolynomial<C>> backSubstituteKronecker( 744 GenPolynomialRing<C> fac, List<GenPolynomial<C>> A, long d) { 745 return ListUtil.<GenPolynomial<C>, GenPolynomial<C>> map(A, new BackSubstKronecker<C>(fac, d)); 746 } 747 748} 749 750 751/** 752 * Kronecker substitutuion functor. 753 */ 754class SubstKronecker<C extends GcdRingElem<C>> implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 755 756 757 final long d; 758 759 760 public SubstKronecker(long d) { 761 this.d = d; 762 } 763 764 765 public GenPolynomial<C> eval(GenPolynomial<C> c) { 766 if (c == null) { 767 return null; 768 } 769 return PolyUfdUtil.<C> substituteKronecker(c, d); 770 } 771} 772 773 774/** 775 * Kronecker back substitutuion functor. 776 */ 777class BackSubstKronecker<C extends GcdRingElem<C>> 778 implements UnaryFunctor<GenPolynomial<C>, GenPolynomial<C>> { 779 780 781 final long d; 782 783 784 final GenPolynomialRing<C> fac; 785 786 787 public BackSubstKronecker(GenPolynomialRing<C> fac, long d) { 788 this.d = d; 789 this.fac = fac; 790 } 791 792 793 public GenPolynomial<C> eval(GenPolynomial<C> c) { 794 if (c == null) { 795 return null; 796 } 797 return PolyUfdUtil.<C> backSubstituteKronecker(fac, c, d); 798 } 799}