001/* 002 * $Id: PseudoReductionSeq.java 5243 2015-05-01 12:42:10Z kredel $ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.List; 009import java.util.Map; 010 011import org.apache.log4j.Logger; 012 013import edu.jas.gb.ReductionAbstract; 014import edu.jas.poly.ExpVector; 015import edu.jas.poly.GenPolynomial; 016import edu.jas.poly.PolyUtil; 017import edu.jas.structure.RingElem; 018 019 020/** 021 * Polynomial pseudo reduction sequential use algorithm. Coefficients of 022 * polynomials must not be from a field, i.e. the fraction free reduction is 023 * implemented. Implements normalform. 024 * @param <C> coefficient type 025 * @author Heinz Kredel 026 */ 027 028public class PseudoReductionSeq<C extends RingElem<C>> extends ReductionAbstract<C> implements 029 PseudoReduction<C> { 030 031 032 private static final Logger logger = Logger.getLogger(PseudoReductionSeq.class); 033 034 035 private final boolean debug = logger.isDebugEnabled(); 036 037 038 /** 039 * Constructor. 040 */ 041 public PseudoReductionSeq() { 042 } 043 044 045 /** 046 * Normalform. 047 * @param Ap polynomial. 048 * @param Pp polynomial list. 049 * @return nf(Ap) with respect to Pp. 050 */ 051 @SuppressWarnings("unchecked") 052 public GenPolynomial<C> normalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 053 if (Pp == null || Pp.isEmpty()) { 054 return Ap; 055 } 056 if (Ap == null || Ap.isZERO()) { 057 return Ap; 058 } 059 Map.Entry<ExpVector, C> m; 060 GenPolynomial<C>[] P = new GenPolynomial[0]; 061 synchronized (Pp) { 062 P = Pp.toArray(P); 063 } 064 int l = P.length; 065 ExpVector[] htl = new ExpVector[l]; 066 C[] lbc = (C[]) new RingElem[l]; 067 GenPolynomial<C>[] p = new GenPolynomial[l]; 068 int i; 069 int j = 0; 070 for (i = 0; i < l; i++) { 071 if (P[i] == null) { 072 continue; 073 } 074 p[i] = P[i]; 075 m = p[i].leadingMonomial(); 076 if (m != null) { 077 p[j] = p[i]; 078 htl[j] = m.getKey(); 079 lbc[j] = m.getValue(); 080 j++; 081 } 082 } 083 l = j; 084 ExpVector e; 085 C a; 086 boolean mt = false; 087 GenPolynomial<C> R = Ap.ring.getZERO().copy(); 088 089 GenPolynomial<C> S = Ap.copy(); 090 while (S.length() > 0) { 091 m = S.leadingMonomial(); 092 e = m.getKey(); 093 a = m.getValue(); 094 for (i = 0; i < l; i++) { 095 mt = e.multipleOf(htl[i]); 096 if (mt) 097 break; 098 } 099 if (!mt) { 100 //logger.debug("irred"); 101 //R = R.sum(a, e); 102 //S = S.subtract(a, e); 103 R.doPutToMap(e, a); 104 S.doRemoveFromMap(e, a); 105 //System.out.println(" S = " + S); 106 } else { 107 e = e.subtract(htl[i]); 108 //logger.info("red div = " + e); 109 @SuppressWarnings("cast") 110 C c = (C) lbc[i]; 111 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 112 a = a.divide(c); 113 S = S.subtractMultiple(a, e, p[i]); 114 } else { 115 R = R.multiply(c); 116 //S = S.multiply(c); 117 S = S.scaleSubtractMultiple(c, a, e, p[i]); 118 } 119 //Q = p[i].multiply(a, e); 120 //S = S.subtract(Q); 121 } 122 } 123 return R; 124 } 125 126 127 /** 128 * Normalform recursive. 129 * @param Ap recursive polynomial. 130 * @param Pp recursive polynomial list. 131 * @return nf(Ap) with respect to Pp. 132 */ 133 @SuppressWarnings("cast") 134 public GenPolynomial<GenPolynomial<C>> normalformRecursive(List<GenPolynomial<GenPolynomial<C>>> Pp, 135 GenPolynomial<GenPolynomial<C>> Ap) { 136 if (Pp == null || Pp.isEmpty()) { 137 return Ap; 138 } 139 if (Ap == null || Ap.isZERO()) { 140 return Ap; 141 } 142 Map.Entry<ExpVector, GenPolynomial<C>> m; 143 GenPolynomial<GenPolynomial<C>>[] P = new GenPolynomial[0]; 144 synchronized (Pp) { 145 P = Pp.toArray(P); 146 } 147 int l = P.length; 148 ExpVector[] htl = new ExpVector[l]; 149 GenPolynomial<C>[] lbc = (GenPolynomial<C>[]) new GenPolynomial[l]; 150 GenPolynomial<GenPolynomial<C>>[] p = new GenPolynomial[l]; 151 int i; 152 int j = 0; 153 for (i = 0; i < l; i++) { 154 if (P[i] == null) { 155 continue; 156 } 157 p[i] = P[i]; 158 m = p[i].leadingMonomial(); 159 if (m != null) { 160 p[j] = p[i]; 161 htl[j] = m.getKey(); 162 lbc[j] = m.getValue(); 163 j++; 164 } 165 } 166 l = j; 167 ExpVector e, f; 168 GenPolynomial<C> a, b; 169 boolean mt = false; 170 GenPolynomial<GenPolynomial<C>> R = Ap.ring.getZERO().copy(); 171 172 GenPolynomial<GenPolynomial<C>> S = Ap.copy(); 173 while (S.length() > 0) { 174 m = S.leadingMonomial(); 175 e = m.getKey(); 176 a = m.getValue(); 177 for (i = 0; i < l; i++) { 178 mt = e.multipleOf(htl[i]); 179 if (mt) 180 break; 181 } 182 if (!mt) { 183 //logger.debug("irred"); 184 //R = R.sum(a, e); 185 //S = S.subtract(a, e); 186 R.doPutToMap(e, a); 187 S.doRemoveFromMap(e, a); 188 //System.out.println(" S = " + S); 189 } else { 190 f = e.subtract(htl[i]); 191 if (debug) { 192 logger.info("red div = " + f); 193 //logger.info("red a = " + a); 194 } 195 GenPolynomial<C> c = (GenPolynomial<C>) lbc[i]; 196 //if (a.remainder(c).isZERO()) { //c.isUnit() ) { 197 if (PolyUtil.<C> baseSparsePseudoRemainder(a, c).isZERO()) { //c.isUnit() ) { 198 if (debug) { 199 logger.info("red c = " + c); 200 } 201 //a = a.divide(c); 202 b = PolyUtil.<C> basePseudoDivide(a, c); 203 GenPolynomial<GenPolynomial<C>> Sp = S.subtractMultiple(b, f, p[i]); 204 if (e.equals(Sp.leadingExpVector())) { // TODO: avoid 205 //throw new RuntimeException("degree not descending"); 206 logger.info("degree not descending: S = " + S + ", Sp = " + Sp); 207 R = R.multiply(c); 208 //S = S.multiply(c); 209 Sp = S.scaleSubtractMultiple(c, a, f, p[i]); 210 } 211 S = Sp; 212 } else { 213 R = R.multiply(c); 214 //S = S.multiply(c); 215 S = S.scaleSubtractMultiple(c, a, f, p[i]); 216 } 217 //Q = p[i].multiply(a, e); 218 //S = S.subtract(Q); 219 } 220 } 221 return R; 222 } 223 224 225 /** 226 * Normalform with recording. <b>Note:</b> Only meaningful if all divisions 227 * are exact. Compute first the multiplication factor <code>m</code> with 228 * <code>normalform(Pp,Ap,m)</code>, then call this method with 229 * <code>normalform(row,Pp,m*Ap)</code>. 230 * @param row recording matrix, is modified. 231 * @param Pp a polynomial list for reduction. 232 * @param Ap a polynomial. 233 * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. 234 */ 235 @SuppressWarnings("unchecked") 236 public GenPolynomial<C> normalform(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp, 237 GenPolynomial<C> Ap) { 238 if (Pp == null || Pp.isEmpty()) { 239 return Ap; 240 } 241 if (Ap == null || Ap.isZERO()) { 242 return Ap; 243 } 244 GenPolynomial<C>[] P = new GenPolynomial[0]; 245 synchronized (Pp) { 246 P = Pp.toArray(P); 247 } 248 int l = P.length; 249 ExpVector[] htl = new ExpVector[l]; 250 Object[] lbc = new Object[l]; // want C 251 GenPolynomial<C>[] p = new GenPolynomial[l]; 252 Map.Entry<ExpVector, C> m; 253 int j = 0; 254 int i; 255 for (i = 0; i < l; i++) { 256 p[i] = P[i]; 257 m = p[i].leadingMonomial(); 258 if (m != null) { 259 p[j] = p[i]; 260 htl[j] = m.getKey(); 261 lbc[j] = m.getValue(); 262 j++; 263 } 264 } 265 l = j; 266 ExpVector e; 267 C a; 268 boolean mt = false; 269 GenPolynomial<C> zero = Ap.ring.getZERO(); 270 GenPolynomial<C> R = Ap.ring.getZERO().copy(); 271 GenPolynomial<C> fac = null; 272 GenPolynomial<C> S = Ap.copy(); 273 while (S.length() > 0) { 274 m = S.leadingMonomial(); 275 e = m.getKey(); 276 a = m.getValue(); 277 for (i = 0; i < l; i++) { 278 mt = e.multipleOf(htl[i]); 279 if (mt) 280 break; 281 } 282 if (!mt) { 283 //logger.debug("irred"); 284 //R = R.sum(a, e); 285 //S = S.subtract(a, e); 286 R.doPutToMap(e, a); 287 S.doRemoveFromMap(e, a); 288 // System.out.println(" S = " + S); 289 } else { 290 e = e.subtract(htl[i]); 291 //logger.info("red div = " + e); 292 C c = (C) lbc[i]; 293 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 294 a = a.divide(c); 295 S = S.subtractMultiple(a, e, p[i]); 296 //System.out.print("|"); 297 } else { 298 //System.out.print("*"); 299 R = R.multiply(c); 300 //S = S.multiply(c); 301 S = S.scaleSubtractMultiple(c, a, e, p[i]); 302 } 303 //Q = p[i].multiply(a, e); 304 //S = S.subtract(Q); 305 fac = row.get(i); 306 if (fac == null) { 307 fac = zero.sum(a, e); 308 } else { 309 fac = fac.sum(a, e); 310 } 311 row.set(i, fac); 312 } 313 } 314 return R; 315 } 316 317 318 /** 319 * Normalform. 320 * @param Pp polynomial list. 321 * @param Ap polynomial. 322 * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor 323 * for Ap. 324 */ 325 @SuppressWarnings("unchecked") 326 public PseudoReductionEntry<C> normalformFactor(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 327 if (Ap == null) { 328 return null; 329 } 330 C mfac = Ap.ring.getONECoefficient(); 331 PseudoReductionEntry<C> pf = new PseudoReductionEntry<C>(Ap, mfac); 332 if (Pp == null || Pp.isEmpty()) { 333 return pf; 334 } 335 if (Ap.isZERO()) { 336 return pf; 337 } 338 Map.Entry<ExpVector, C> m; 339 GenPolynomial<C>[] P = new GenPolynomial[0]; 340 synchronized (Pp) { 341 P = Pp.toArray(P); 342 } 343 int l = P.length; 344 ExpVector[] htl = new ExpVector[l]; 345 C[] lbc = (C[]) new RingElem[l]; // want C[] 346 GenPolynomial<C>[] p = new GenPolynomial[l]; 347 int i; 348 int j = 0; 349 for (i = 0; i < l; i++) { 350 if (P[i] == null) { 351 continue; 352 } 353 p[i] = P[i]; 354 m = p[i].leadingMonomial(); 355 if (m != null) { 356 p[j] = p[i]; 357 htl[j] = m.getKey(); 358 lbc[j] = m.getValue(); 359 j++; 360 } 361 } 362 l = j; 363 ExpVector e; 364 C a; 365 boolean mt = false; 366 GenPolynomial<C> R = Ap.ring.getZERO().copy(); 367 368 GenPolynomial<C> S = Ap.copy(); 369 while (S.length() > 0) { 370 m = S.leadingMonomial(); 371 e = m.getKey(); 372 a = m.getValue(); 373 for (i = 0; i < l; i++) { 374 mt = e.multipleOf(htl[i]); 375 if (mt) 376 break; 377 } 378 if (!mt) { 379 //logger.debug("irred"); 380 //R = R.sum(a, e); 381 //S = S.subtract(a, e); 382 R.doPutToMap(e, a); 383 S.doRemoveFromMap(e, a); 384 //System.out.println(" S = " + S); 385 } else { 386 e = e.subtract(htl[i]); 387 //logger.info("red div = " + e); 388 C c = lbc[i]; 389 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 390 a = a.divide(c); 391 S = S.subtractMultiple(a, e, p[i]); 392 } else { 393 mfac = mfac.multiply(c); 394 R = R.multiply(c); 395 //S = S.multiply(c); 396 S = S.scaleSubtractMultiple(c, a, e, p[i]); 397 } 398 //Q = p[i].multiply(a, e); 399 //S = S.subtract(Q); 400 } 401 } 402 if (logger.isInfoEnabled()) { 403 logger.info("multiplicative factor = " + mfac); 404 } 405 pf = new PseudoReductionEntry<C>(R, mfac); 406 return pf; 407 } 408 409}