001/* 002 * $Id$ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011import java.util.SortedMap; 012import java.util.TreeMap; 013 014import org.apache.logging.log4j.LogManager; 015import org.apache.logging.log4j.Logger; 016 017import edu.jas.poly.GenPolynomial; 018import edu.jas.poly.GenPolynomialRing; 019import edu.jas.poly.PolyUtil; 020import edu.jas.structure.GcdRingElem; 021import edu.jas.structure.RingFactory; 022 023 024/** 025 * Abstract squarefree decomposition class. 026 * @author Heinz Kredel 027 */ 028 029public abstract class SquarefreeAbstract<C extends GcdRingElem<C>> implements Squarefree<C> { 030 031 032 private static final Logger logger = LogManager.getLogger(SquarefreeAbstract.class); 033 034 035 /** 036 * GCD engine for respective base coefficients. 037 */ 038 protected final GreatestCommonDivisorAbstract<C> engine; 039 040 041 /** 042 * Constructor. 043 */ 044 public SquarefreeAbstract(GreatestCommonDivisorAbstract<C> engine) { 045 this.engine = engine; 046 } 047 048 049 /** 050 * GenPolynomial polynomial greatest squarefree divisor. 051 * @param P GenPolynomial. 052 * @return squarefree(pp(P)). 053 */ 054 public abstract GenPolynomial<C> baseSquarefreePart(GenPolynomial<C> P); 055 056 057 /** 058 * GenPolynomial polynomial squarefree factorization. 059 * @param A GenPolynomial. 060 * @return [p_1 -> e_1, ..., p_k -> e_k] with A = prod_{i=1,...,k} 061 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 062 */ 063 public abstract SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A); 064 065 066 /** 067 * GenPolynomial recursive polynomial greatest squarefree divisor. 068 * @param P recursive univariate GenPolynomial. 069 * @return squarefree(pp(P)). 070 */ 071 public abstract GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart( 072 GenPolynomial<GenPolynomial<C>> P); 073 074 075 /** 076 * GenPolynomial recursive univariate polynomial squarefree factorization. 077 * @param P recursive univariate GenPolynomial. 078 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 079 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 080 */ 081 public abstract SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors( 082 GenPolynomial<GenPolynomial<C>> P); 083 084 085 /** 086 * GenPolynomial greatest squarefree divisor. 087 * @param P GenPolynomial. 088 * @return squarefree(P) a primitive respectively monic polynomial. 089 */ 090 public abstract GenPolynomial<C> squarefreePart(GenPolynomial<C> P); 091 092 093 /** 094 * GenPolynomial test if is squarefree. 095 * @param P GenPolynomial. 096 * @return true if P is squarefree, else false. 097 */ 098 public boolean isSquarefree(GenPolynomial<C> P) { 099 GenPolynomial<C> S = squarefreePart(P); 100 GenPolynomial<C> Ps = P; 101 if (P.ring.coFac.isField()) { 102 Ps = Ps.monic(); 103 } else { 104 Ps = engine.basePrimitivePart(Ps); 105 } 106 boolean f = Ps.equals(S); 107 return f; 108 } 109 110 111 /** 112 * GenPolynomial list test if squarefree. 113 * @param L list of GenPolynomial. 114 * @return true if each P in L is squarefree, else false. 115 */ 116 public boolean isSquarefree(List<GenPolynomial<C>> L) { 117 if (L == null || L.isEmpty()) { 118 return true; 119 } 120 for (GenPolynomial<C> P : L) { 121 if (!isSquarefree(P)) { 122 return false; 123 } 124 } 125 return true; 126 } 127 128 129 /** 130 * Recursive GenPolynomial test if is squarefree. 131 * @param P recursive univariate GenPolynomial. 132 * @return true if P is squarefree, else false. 133 */ 134 public boolean isRecursiveSquarefree(GenPolynomial<GenPolynomial<C>> P) { 135 GenPolynomial<GenPolynomial<C>> S = recursiveUnivariateSquarefreePart(P); 136 boolean f = P.equals(S); 137 if (!f) { 138 logger.info("not Squarefree, S != P: {} != {}", P, S); 139 } 140 return f; 141 } 142 143 144 /** 145 * GenPolynomial squarefree factorization. 146 * @param P GenPolynomial. 147 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 148 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 149 */ 150 public abstract SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P); 151 152 153 /** 154 * GenPolynomial squarefree and co-prime list. 155 * @param A list of GenPolynomials. 156 * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant 157 * a in A there exists b in B with b|a and each b in B is 158 * squarefree. B does not contain zero or constant polynomials. 159 */ 160 public List<GenPolynomial<C>> coPrimeSquarefree(List<GenPolynomial<C>> A) { 161 if (A == null || A.isEmpty()) { 162 return A; 163 } 164 List<GenPolynomial<C>> S = new ArrayList<GenPolynomial<C>>(); 165 for (GenPolynomial<C> g : A) { 166 SortedMap<GenPolynomial<C>, Long> sm = squarefreeFactors(g); 167 S.addAll(sm.keySet()); 168 } 169 List<GenPolynomial<C>> B = engine.coPrime(S); 170 return B; 171 } 172 173 174 /** 175 * GenPolynomial squarefree and co-prime list. 176 * @param a polynomial. 177 * @param P squarefree co-prime list of GenPolynomials. 178 * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a 179 * there exists b in P with b|a. B does not contain zero or constant 180 * polynomials. 181 */ 182 public List<GenPolynomial<C>> coPrimeSquarefree(GenPolynomial<C> a, List<GenPolynomial<C>> P) { 183 if (a == null || a.isZERO() || a.isConstant()) { 184 return P; 185 } 186 SortedMap<GenPolynomial<C>, Long> sm = squarefreeFactors(a); 187 List<GenPolynomial<C>> B = P; 188 for (GenPolynomial<C> f : sm.keySet()) { 189 B = engine.coPrime(f, B); 190 } 191 return B; 192 } 193 194 195 /** 196 * Test if list of GenPolynomials is squarefree and co-prime. 197 * @param B list of GenPolynomials. 198 * @return true, if for all b != c in B gcd(b,c) = 1 and each b in B is 199 * squarefree, else false. 200 */ 201 public boolean isCoPrimeSquarefree(List<GenPolynomial<C>> B) { 202 if (B == null || B.isEmpty()) { 203 return true; 204 } 205 if (!engine.isCoPrime(B)) { 206 return false; 207 } 208 return isSquarefree(B); 209 } 210 211 212 /** 213 * Normalize factorization. p'_i > 0 for i > 1 and p'_1 != 1 if k > 214 * 1. 215 * @param F = [p_1->e_1;, ..., p_k->e_k]. 216 * @return F' = [p'_1->e_1, ..., p'_k->e_k]. 217 */ 218 public SortedMap<GenPolynomial<C>, Long> normalizeFactorization(SortedMap<GenPolynomial<C>, Long> F) { 219 if (F == null || F.size() <= 1) { 220 return F; 221 } 222 List<GenPolynomial<C>> Fp = new ArrayList<GenPolynomial<C>>(F.keySet()); 223 GenPolynomial<C> f0 = Fp.get(0); 224 if (f0.ring.characteristic().signum() != 0) { // only ordered coefficients 225 return F; 226 } 227 long e0 = F.get(f0); 228 SortedMap<GenPolynomial<C>, Long> Sp = new TreeMap<GenPolynomial<C>, Long>(); 229 for (int i = 1; i < Fp.size(); i++) { 230 GenPolynomial<C> fi = Fp.get(i); 231 long ei = F.get(fi); 232 if (fi.signum() < 0) { 233 //System.out.println("e0 = " + e0 + ", f0 = " + f0); 234 //System.out.println("ei = " + ei + ", fi = " + fi); 235 if (ei % 2 != 0 && e0 % 2 != 0) { // bug 236 fi = fi.negate(); 237 f0 = f0.negate(); 238 } 239 } 240 Sp.put(fi, ei); 241 } 242 if (!f0.isONE()) { 243 Sp.put(f0, e0); 244 } 245 return Sp; 246 } 247 248 249 /** 250 * GenPolynomial is (squarefree) factorization. 251 * @param P GenPolynomial. 252 * @param F = [p_1, ..., p_k]. 253 * @return true if P = prod_{i=1,...,r} p_i, else false. 254 */ 255 public boolean isFactorization(GenPolynomial<C> P, List<GenPolynomial<C>> F) { 256 if (P == null || F == null) { 257 throw new IllegalArgumentException("P and F may not be null"); 258 } 259 if (P.isZERO() && F.size() == 0) { 260 return true; 261 } 262 GenPolynomial<C> t = P.ring.getONE(); 263 for (GenPolynomial<C> f : F) { 264 t = t.multiply(f); 265 } 266 boolean f = P.equals(t) || P.equals(t.negate()); 267 if (!f) { 268 logger.info("no factorization(list): F = {}, P = {}, t = {}", F, P, t); 269 } 270 return f; 271 } 272 273 274 /** 275 * Count number of factors in a (squarefree) factorization. 276 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 277 * @return sum_{i=1,...,k} e_i. 278 */ 279 public long factorCount(SortedMap<GenPolynomial<C>, Long> F) { 280 if (F == null || F.isEmpty()) { 281 return 0L; 282 } 283 long f = 0L; 284 for (Long e : F.values()) { 285 f += e; 286 } 287 return f; 288 } 289 290 291 /** 292 * GenPolynomial is (squarefree) factorization. 293 * @param P GenPolynomial. 294 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 295 * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. 296 */ 297 public boolean isFactorization(GenPolynomial<C> P, SortedMap<GenPolynomial<C>, Long> F) { 298 if (P == null || F == null) { 299 throw new IllegalArgumentException("P and F may not be null"); 300 } 301 if (P.isZERO() && F.size() == 0) { 302 return true; 303 } 304 GenPolynomial<C> t = P.ring.getONE(); 305 for (Map.Entry<GenPolynomial<C>, Long> me : F.entrySet()) { 306 GenPolynomial<C> f = me.getKey(); 307 Long E = me.getValue(); 308 long e = E.longValue(); 309 GenPolynomial<C> g = f.power(e); 310 t = t.multiply(g); 311 } 312 boolean f = P.equals(t) || P.equals(t.negate()); 313 if (!f) { 314 P = P.monic(); 315 t = t.monic(); 316 f = P.equals(t) || P.equals(t.negate()); 317 if (f) { 318 return f; 319 } 320 logger.info("no factorization(map): F = {}, P = {}, t = {}", F, P, t); 321 //RuntimeException e = new RuntimeException("fac-map"); 322 //e.printStackTrace(); 323 //throw e; 324 } 325 return f; 326 } 327 328 329 /** 330 * GenPolynomial is (squarefree) factorization. 331 * @param P GenPolynomial. 332 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 333 * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. 334 */ 335 public boolean isRecursiveFactorization(GenPolynomial<GenPolynomial<C>> P, 336 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> F) { 337 if (P == null || F == null) { 338 throw new IllegalArgumentException("P and F may not be null"); 339 } 340 if (P.isZERO() && F.size() == 0) { 341 return true; 342 } 343 GenPolynomial<GenPolynomial<C>> t = P.ring.getONE(); 344 for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> me : F.entrySet()) { 345 GenPolynomial<GenPolynomial<C>> f = me.getKey(); 346 Long E = me.getValue(); // F.get(f); 347 long e = E.longValue(); 348 GenPolynomial<GenPolynomial<C>> g = f.power(e); 349 t = t.multiply(g); 350 } 351 boolean f = P.equals(t) || P.equals(t.negate()); 352 if (!f) { 353 GenPolynomialRing<C> cf = (GenPolynomialRing<C>) P.ring.coFac; 354 GreatestCommonDivisorAbstract<C> engine = GCDFactory.getProxy(cf.coFac); 355 GenPolynomial<GenPolynomial<C>> Pp = engine.recursivePrimitivePart(P); 356 Pp = PolyUtil.<C> monic(Pp); 357 GenPolynomial<GenPolynomial<C>> tp = engine.recursivePrimitivePart(t); 358 tp = PolyUtil.<C> monic(tp); 359 f = Pp.equals(tp) || Pp.equals(tp.negate()); 360 if (f) { 361 return f; 362 } 363 logger.info("no factorization(map): F = {}, P = {}, t = {}, Pp = {}, tp = {}", F, P, t, Pp, tp); 364 //RuntimeException e = new RuntimeException("fac-map"); 365 //e.printStackTrace(); 366 //throw e; 367 } 368 return f; 369 } 370 371 372 /** 373 * GenPolynomial recursive polynomial greatest squarefree divisor. 374 * @param P recursive GenPolynomial. 375 * @return squarefree(pp(P)). 376 */ 377 public GenPolynomial<GenPolynomial<C>> recursiveSquarefreePart(GenPolynomial<GenPolynomial<C>> P) { 378 if (P == null || P.isZERO()) { 379 return P; 380 } 381 if (P.ring.nvar <= 1) { 382 return recursiveUnivariateSquarefreePart(P); 383 } 384 // distributed polynomials squarefree part 385 GenPolynomialRing<GenPolynomial<C>> rfac = P.ring; 386 RingFactory<GenPolynomial<C>> rrfac = rfac.coFac; 387 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rrfac; 388 GenPolynomialRing<C> dfac = cfac.extend(rfac.nvar); 389 GenPolynomial<C> Pd = PolyUtil.<C> distribute(dfac, P); 390 GenPolynomial<C> Dd = squarefreePart(Pd); 391 // convert to recursive 392 GenPolynomial<GenPolynomial<C>> C = PolyUtil.<C> recursive(rfac, Dd); 393 return C; 394 } 395 396 397 /** 398 * GenPolynomial recursive polynomial squarefree factorization. 399 * @param P recursive GenPolynomial. 400 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 401 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 402 */ 403 public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveSquarefreeFactors( 404 GenPolynomial<GenPolynomial<C>> P) { 405 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> factors; 406 factors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>(); 407 if (P == null || P.isZERO()) { 408 return factors; 409 } 410 if (P.ring.nvar <= 1) { 411 return recursiveUnivariateSquarefreeFactors(P); 412 } 413 // distributed polynomials squarefree part 414 GenPolynomialRing<GenPolynomial<C>> rfac = P.ring; 415 RingFactory<GenPolynomial<C>> rrfac = rfac.coFac; 416 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rrfac; 417 GenPolynomialRing<C> dfac = cfac.extend(rfac.nvar); 418 GenPolynomial<C> Pd = PolyUtil.<C> distribute(dfac, P); 419 SortedMap<GenPolynomial<C>, Long> dfacs = squarefreeFactors(Pd); 420 // convert to recursive 421 for (Map.Entry<GenPolynomial<C>, Long> Dm : dfacs.entrySet()) { 422 GenPolynomial<C> Dd = Dm.getKey(); 423 Long e = Dm.getValue(); 424 GenPolynomial<GenPolynomial<C>> C = PolyUtil.<C> recursive(rfac, Dd); 425 factors.put(C, e); 426 } 427 return factors; 428 } 429 430 431 /** 432 * Univariate GenPolynomial partial fraction decomposition. 433 * @param A univariate GenPolynomial. 434 * @param D sorted map [d_1 -> e_1, ..., d_k -> e_k] with d_i 435 * squarefree. 436 * @return [ [Ai0, Ai1,..., Aie_i], i=0,...,k ] with A/prod(D) = A0 + sum( 437 * sum ( Aij/di^j ) ) with deg(Aij) < deg(di). 438 */ 439 public List<List<GenPolynomial<C>>> basePartialFraction(GenPolynomial<C> A, 440 SortedMap<GenPolynomial<C>, Long> D) { 441 if (D == null || A == null) { 442 throw new IllegalArgumentException("null A or D not allowed"); 443 } 444 List<List<GenPolynomial<C>>> pf = new ArrayList<List<GenPolynomial<C>>>(D.size() + 1); 445 if (D.size() == 0) { 446 return pf; 447 } 448 //List<GenPolynomial<C>> fi; 449 if (A.isZERO()) { 450 for (Map.Entry<GenPolynomial<C>, Long> me : D.entrySet()) { 451 long e = me.getValue(); 452 int e1 = (int) e + 1; 453 List<GenPolynomial<C>> fi = new ArrayList<GenPolynomial<C>>(e1); 454 for (int i = 0; i < e1; i++) { 455 fi.add(A); 456 } 457 pf.add(fi); 458 } 459 List<GenPolynomial<C>> fi = new ArrayList<GenPolynomial<C>>(1); 460 fi.add(A); 461 pf.add(0, fi); 462 return pf; 463 } 464 // A != 0, D != empty 465 List<GenPolynomial<C>> Dp = new ArrayList<GenPolynomial<C>>(D.size()); 466 for (Map.Entry<GenPolynomial<C>, Long> me : D.entrySet()) { 467 GenPolynomial<C> d = me.getKey(); 468 long e = me.getValue(); //D.get(d); 469 GenPolynomial<C> f = d.power(e); 470 Dp.add(f); 471 } 472 List<GenPolynomial<C>> F = engine.basePartialFraction(A, Dp); 473 //System.out.println("fraction list = " + F.size()); 474 GenPolynomial<C> A0 = F.remove(0); 475 List<GenPolynomial<C>> fi = new ArrayList<GenPolynomial<C>>(1); 476 fi.add(A0); 477 pf.add(fi); 478 int i = 0; 479 for (Map.Entry<GenPolynomial<C>, Long> me : D.entrySet()) { // assume fixed sequence order 480 GenPolynomial<C> d = me.getKey(); 481 long e = me.getValue(); 482 int ei = (int) e; 483 GenPolynomial<C> gi = F.get(i); // assume fixed sequence order 484 List<GenPolynomial<C>> Fi = engine.basePartialFraction(gi, d, ei); 485 pf.add(Fi); 486 i++; 487 } 488 return pf; 489 } 490 491 492 /** 493 * Test for Univariate GenPolynomial partial fraction decomposition. 494 * @param A univariate GenPolynomial. 495 * @param D sorted map [d_1 -> e_1, ..., d_k -> e_k] with d_i 496 * squarefree. 497 * @param F a list of lists [ [Ai0, Ai1,..., Aie_i], i=0,...,k ] 498 * @return true, if A/prod(D) = A0 + sum( sum ( Aij/di^j ) ), else false. 499 */ 500 public boolean isBasePartialFraction(GenPolynomial<C> A, SortedMap<GenPolynomial<C>, Long> D, 501 List<List<GenPolynomial<C>>> F) { 502 if (D == null || A == null || F == null) { 503 throw new IllegalArgumentException("null A, D or F not allowed"); 504 } 505 if (D.isEmpty() && F.isEmpty()) { 506 return true; 507 } 508 if (D.isEmpty() || F.isEmpty()) { 509 return false; 510 } 511 List<GenPolynomial<C>> Dp = new ArrayList<GenPolynomial<C>>(D.size()); 512 for (Map.Entry<GenPolynomial<C>, Long> me : D.entrySet()) { 513 GenPolynomial<C> d = me.getKey(); 514 long e = me.getValue(); // D.get(d); 515 GenPolynomial<C> f = d.power(e); 516 Dp.add(f); 517 } 518 List<GenPolynomial<C>> fi = F.get(0); 519 if (fi.size() != 1) { 520 logger.info("size(fi) != 1 {}", fi); 521 return false; 522 } 523 boolean t; 524 GenPolynomial<C> A0 = fi.get(0); 525 //System.out.println("A0 = " + A0); 526 List<GenPolynomial<C>> Qp = new ArrayList<GenPolynomial<C>>(D.size() + 1); 527 Qp.add(A0); 528 529 // List<GenPolynomial<C>> Fp = engine.basePartialFraction(A,Dp); 530 // System.out.println("fraction list = " + F.size()); 531 // t = engine.isBasePartialFraction(A,Dp,Fp); 532 // if ( ! t ) { 533 // System.out.println("not recursion isPartFrac = " + Fp); 534 // return false; 535 // } 536 // GenPolynomial<C> A0p = Fp.remove(0); 537 // if ( ! A0.equals(A0p) ) { 538 // System.out.println("A0 != A0p " + A0p); 539 // return false; 540 // } 541 542 int i = 0; 543 for (Map.Entry<GenPolynomial<C>, Long> me : D.entrySet()) { // assume fixed sequence order 544 GenPolynomial<C> d = me.getKey(); 545 long e = me.getValue(); 546 int ei = (int) e; 547 List<GenPolynomial<C>> Fi = F.get(i + 1); // assume fixed sequence order 548 549 // GenPolynomial<C> pi = Fp.get(i); // assume fixed sequence order 550 // t = engine.isBasePartialFraction(pi,d,ei,Fi); 551 // if ( ! t ) { 552 // System.out.println("not isPartFrac exp = " + pi + ", d = " + d + ", e = " + ei); 553 // System.out.println("not isPartFrac exp = " + Fi); 554 // return false; 555 // } 556 557 GenPolynomial<C> qi = engine.basePartialFractionValue(d, ei, Fi); 558 Qp.add(qi); 559 560 // t = qi.equals(pi); 561 // if ( ! t ) { 562 // System.out.println("not isPartFrac exp = " + pi + ", d = " + d + ", e = " + ei + ", qi = " + qi); 563 // } 564 565 i++; 566 } 567 568 t = engine.isBasePartialFraction(A, Dp, Qp); 569 if (!t) { 570 System.out.println("not final isPartFrac " + Qp); 571 } 572 return t; 573 } 574 575 576 /** 577 * Coefficients greatest squarefree divisor. 578 * @param P coefficient. 579 * @return squarefree part of P. 580 */ 581 public C squarefreePart(C P) { 582 if (P == null) { 583 return null; 584 } 585 C s = null; 586 SortedMap<C, Long> factors = squarefreeFactors(P); 587 //if (logger.isWarnEnabled()) { 588 // logger.warn("sqfPart, better use sqfFactors, factors = {}", factors); 589 //} 590 for (C sp : factors.keySet()) { 591 if (s == null) { 592 s = sp; 593 } else { 594 s = s.multiply(sp); 595 } 596 } 597 return s; 598 } 599 600 601 /** 602 * Coefficients squarefree factorization. 603 * @param P coefficient. 604 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 605 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 606 */ 607 public abstract SortedMap<C, Long> squarefreeFactors(C P); 608 /* not possible: 609 { 610 if (P == null) { 611 return null; 612 } 613 SortedMap<C, Long> factors = new TreeMap<C, Long>(); 614 SquarefreeAbstract<C> reng = SquarefreeFactory.getImplementation((RingFactory<C>) P.factory()); 615 System.out.println("fcp,reng = " + reng); 616 SortedMap<C, Long> rfactors = reng.squarefreeFactors(P); 617 for (C c : rfactors.keySet()) { 618 if (!c.isONE()) { 619 C cr = (C) (Object) c; 620 Long rk = rfactors.get(c); 621 factors.put(cr, rk); 622 } 623 } 624 625 return factors; 626 } 627 */ 628 629}