001/* 002 * $Id: PseudoReductionSeq.java 5841 2018-05-20 21:26:13Z 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 static 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, f; 085 C a, b; 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 f = e.subtract(htl[i]); 108 //logger.info("red div = " + e); 109 @SuppressWarnings("unchecked") 110 C c = (C) lbc[i]; 111 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 112 b = a.divide(c); 113 GenPolynomial<C> Sp = S.subtractMultiple(b, f, p[i]); 114 if (e.equals(Sp.leadingExpVector())) { // TODO: avoid if possible 115 logger.info("degree not descending: S = " + S + ", Sp = " + Sp); 116 R = R.multiply(c); 117 //S = S.multiply(c); 118 Sp = S.scaleSubtractMultiple(c, a, f, p[i]); 119 } 120 S = Sp; 121 } else { 122 R = R.multiply(c); 123 //S = S.multiply(c); 124 S = S.scaleSubtractMultiple(c, a, f, p[i]); 125 } 126 //Q = p[i].multiply(a, e); 127 //S = S.subtract(Q); 128 } 129 } 130 return R; 131 } 132 133 134 /** 135 * Normalform recursive. 136 * @param Ap recursive polynomial. 137 * @param Pp recursive polynomial list. 138 * @return nf(Ap) with respect to Pp. 139 */ 140 @SuppressWarnings("unchecked") 141 public GenPolynomial<GenPolynomial<C>> normalformRecursive(List<GenPolynomial<GenPolynomial<C>>> Pp, 142 GenPolynomial<GenPolynomial<C>> Ap) { 143 if (Pp == null || Pp.isEmpty()) { 144 return Ap; 145 } 146 if (Ap == null || Ap.isZERO()) { 147 return Ap; 148 } 149 Map.Entry<ExpVector, GenPolynomial<C>> m; 150 GenPolynomial<GenPolynomial<C>>[] P = new GenPolynomial[0]; 151 synchronized (Pp) { 152 P = Pp.toArray(P); 153 } 154 int l = P.length; 155 ExpVector[] htl = new ExpVector[l]; 156 GenPolynomial<C>[] lbc = (GenPolynomial<C>[]) new GenPolynomial[l]; 157 GenPolynomial<GenPolynomial<C>>[] p = new GenPolynomial[l]; 158 int i; 159 int j = 0; 160 for (i = 0; i < l; i++) { 161 if (P[i] == null) { 162 continue; 163 } 164 p[i] = P[i]; 165 m = p[i].leadingMonomial(); 166 if (m != null) { 167 p[j] = p[i]; 168 htl[j] = m.getKey(); 169 lbc[j] = m.getValue(); 170 j++; 171 } 172 } 173 l = j; 174 ExpVector e, f; 175 GenPolynomial<C> a, b; 176 boolean mt = false; 177 GenPolynomial<GenPolynomial<C>> R = Ap.ring.getZERO().copy(); 178 179 GenPolynomial<GenPolynomial<C>> S = Ap.copy(); 180 while (S.length() > 0) { 181 m = S.leadingMonomial(); 182 e = m.getKey(); 183 a = m.getValue(); 184 for (i = 0; i < l; i++) { 185 mt = e.multipleOf(htl[i]); 186 if (mt) 187 break; 188 } 189 if (!mt) { 190 //logger.debug("irred"); 191 //R = R.sum(a, e); 192 //S = S.subtract(a, e); 193 R.doPutToMap(e, a); 194 S.doRemoveFromMap(e, a); 195 //System.out.println(" S = " + S); 196 } else { 197 f = e.subtract(htl[i]); 198 if (debug) { 199 logger.info("red div = " + f); 200 //logger.info("red a = " + a); 201 } 202 GenPolynomial<C> c = (GenPolynomial<C>) lbc[i]; 203 //if (a.remainder(c).isZERO()) { //c.isUnit() ) { 204 if (PolyUtil.<C> baseSparsePseudoRemainder(a, c).isZERO()) { //c.isUnit() ) { 205 if (debug) { 206 logger.info("red c = " + c); 207 } 208 //a = a.divide(c); 209 b = PolyUtil.<C> basePseudoDivide(a, c); 210 GenPolynomial<GenPolynomial<C>> Sp = S.subtractMultiple(b, f, p[i]); 211 if (e.equals(Sp.leadingExpVector())) { // TODO: avoid if possible 212 //throw new RuntimeException("degree not descending"); 213 logger.info("degree not descending: S = " + S + ", Sp = " + Sp); 214 R = R.multiply(c); 215 //S = S.multiply(c); 216 Sp = S.scaleSubtractMultiple(c, a, f, p[i]); 217 } 218 S = Sp; 219 } else { 220 R = R.multiply(c); 221 //S = S.multiply(c); 222 S = S.scaleSubtractMultiple(c, a, f, p[i]); 223 } 224 //Q = p[i].multiply(a, e); 225 //S = S.subtract(Q); 226 } 227 } 228 return R; 229 } 230 231 232 /** 233 * Normalform with recording. <b>Note:</b> Only meaningful if all divisions 234 * are exact. Compute first the multiplication factor <code>m</code> with 235 * <code>normalform(Pp,Ap,m)</code>, then call this method with 236 * <code>normalform(row,Pp,m*Ap)</code>. 237 * @param row recording matrix, is modified. 238 * @param Pp a polynomial list for reduction. 239 * @param Ap a polynomial. 240 * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. 241 */ 242 @SuppressWarnings("unchecked") 243 public GenPolynomial<C> normalform(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp, 244 GenPolynomial<C> Ap) { 245 if (Pp == null || Pp.isEmpty()) { 246 return Ap; 247 } 248 if (Ap == null || Ap.isZERO()) { 249 return Ap; 250 } 251 GenPolynomial<C>[] P = new GenPolynomial[0]; 252 synchronized (Pp) { 253 P = Pp.toArray(P); 254 } 255 int l = P.length; 256 ExpVector[] htl = new ExpVector[l]; 257 Object[] lbc = new Object[l]; // want C 258 GenPolynomial<C>[] p = new GenPolynomial[l]; 259 Map.Entry<ExpVector, C> m; 260 int j = 0; 261 int i; 262 for (i = 0; i < l; i++) { 263 p[i] = P[i]; 264 m = p[i].leadingMonomial(); 265 if (m != null) { 266 p[j] = p[i]; 267 htl[j] = m.getKey(); 268 lbc[j] = m.getValue(); 269 j++; 270 } 271 } 272 l = j; 273 ExpVector e; 274 C a; 275 boolean mt = false; 276 GenPolynomial<C> zero = Ap.ring.getZERO(); 277 GenPolynomial<C> R = Ap.ring.getZERO().copy(); 278 GenPolynomial<C> fac = null; 279 GenPolynomial<C> S = Ap.copy(); 280 while (S.length() > 0) { 281 m = S.leadingMonomial(); 282 e = m.getKey(); 283 a = m.getValue(); 284 for (i = 0; i < l; i++) { 285 mt = e.multipleOf(htl[i]); 286 if (mt) 287 break; 288 } 289 if (!mt) { 290 //logger.debug("irred"); 291 //R = R.sum(a, e); 292 //S = S.subtract(a, e); 293 R.doPutToMap(e, a); 294 S.doRemoveFromMap(e, a); 295 // System.out.println(" S = " + S); 296 } else { 297 e = e.subtract(htl[i]); 298 //logger.info("red div = " + e); 299 C c = (C) lbc[i]; 300 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 301 a = a.divide(c); 302 S = S.subtractMultiple(a, e, p[i]); 303 //System.out.print("|"); 304 } else { 305 //System.out.print("*"); 306 R = R.multiply(c); 307 //S = S.multiply(c); 308 S = S.scaleSubtractMultiple(c, a, e, p[i]); 309 } 310 //Q = p[i].multiply(a, e); 311 //S = S.subtract(Q); 312 fac = row.get(i); 313 if (fac == null) { 314 fac = zero.sum(a, e); 315 } else { 316 fac = fac.sum(a, e); 317 } 318 row.set(i, fac); 319 } 320 } 321 return R; 322 } 323 324 325 /** 326 * Normalform. 327 * @param Pp polynomial list. 328 * @param Ap polynomial. 329 * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor 330 * for Ap. 331 */ 332 @SuppressWarnings("unchecked") 333 public PseudoReductionEntry<C> normalformFactor(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 334 if (Ap == null) { 335 return null; 336 } 337 C mfac = Ap.ring.getONECoefficient(); 338 PseudoReductionEntry<C> pf = new PseudoReductionEntry<C>(Ap, mfac); 339 if (Pp == null || Pp.isEmpty()) { 340 return pf; 341 } 342 if (Ap.isZERO()) { 343 return pf; 344 } 345 Map.Entry<ExpVector, C> m; 346 GenPolynomial<C>[] P = new GenPolynomial[0]; 347 synchronized (Pp) { 348 P = Pp.toArray(P); 349 } 350 int l = P.length; 351 ExpVector[] htl = new ExpVector[l]; 352 C[] lbc = (C[]) new RingElem[l]; // want C[] 353 GenPolynomial<C>[] p = new GenPolynomial[l]; 354 int i; 355 int j = 0; 356 for (i = 0; i < l; i++) { 357 if (P[i] == null) { 358 continue; 359 } 360 p[i] = P[i]; 361 m = p[i].leadingMonomial(); 362 if (m != null) { 363 p[j] = p[i]; 364 htl[j] = m.getKey(); 365 lbc[j] = m.getValue(); 366 j++; 367 } 368 } 369 l = j; 370 ExpVector e; 371 C a; 372 boolean mt = false; 373 GenPolynomial<C> R = Ap.ring.getZERO().copy(); 374 375 GenPolynomial<C> S = Ap.copy(); 376 while (S.length() > 0) { 377 m = S.leadingMonomial(); 378 e = m.getKey(); 379 a = m.getValue(); 380 for (i = 0; i < l; i++) { 381 mt = e.multipleOf(htl[i]); 382 if (mt) 383 break; 384 } 385 if (!mt) { 386 //logger.debug("irred"); 387 //R = R.sum(a, e); 388 //S = S.subtract(a, e); 389 R.doPutToMap(e, a); 390 S.doRemoveFromMap(e, a); 391 //System.out.println(" S = " + S); 392 } else { 393 e = e.subtract(htl[i]); 394 //logger.info("red div = " + e); 395 C c = lbc[i]; 396 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 397 a = a.divide(c); 398 S = S.subtractMultiple(a, e, p[i]); 399 } else { 400 mfac = mfac.multiply(c); 401 R = R.multiply(c); 402 //S = S.multiply(c); 403 S = S.scaleSubtractMultiple(c, a, e, p[i]); 404 } 405 //Q = p[i].multiply(a, e); 406 //S = S.subtract(Q); 407 } 408 } 409 if (logger.isInfoEnabled()) { 410 logger.info("multiplicative factor = " + mfac); 411 } 412 pf = new PseudoReductionEntry<C>(R, mfac); 413 return pf; 414 } 415 416}