001/* 002 * $Id$ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011 012import org.apache.logging.log4j.Logger; 013import org.apache.logging.log4j.LogManager; 014 015import edu.jas.gb.ReductionAbstract; 016import edu.jas.poly.PolyUtil; 017import edu.jas.poly.ExpVector; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.structure.RingElem; 020 021 022/** 023 * Polynomial pseudo reduction sequential use algorithm. Coefficients of 024 * polynomials must not be from a field, i.e. the fraction free reduction is 025 * implemented. Implements normalform. 026 * @param <C> coefficient type 027 * @author Heinz Kredel 028 */ 029 030public class PseudoReductionPar<C extends RingElem<C>> extends ReductionAbstract<C> implements 031 PseudoReduction<C> { 032 033 034 private static final Logger logger = LogManager.getLogger(PseudoReductionPar.class); 035 036 037 private static final boolean debug = logger.isDebugEnabled(); 038 039 040 /** 041 * Constructor. 042 */ 043 public PseudoReductionPar() { 044 } 045 046 047 /** 048 * Normalform. 049 * @param Ap polynomial. 050 * @param Pp polynomial list. 051 * @return nf(Ap) with respect to Pp. 052 */ 053 @SuppressWarnings("unchecked") 054 public GenPolynomial<C> normalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 055 if (Pp == null || Pp.isEmpty()) { 056 return Ap; 057 } 058 if (Ap == null || Ap.isZERO()) { 059 return Ap; 060 } 061 GenPolynomial<C>[] P = new GenPolynomial[0]; 062 List<GenPolynomial<C>> Ppp; 063 synchronized (Pp) { 064 Ppp = new ArrayList<GenPolynomial<C>>(Pp); // sic 065 } 066 P = Ppp.toArray(P); 067 int ll = Ppp.size(); 068 GenPolynomial<C> Rz = Ap.ring.getZERO(); 069 GenPolynomial<C> R = Rz.copy(); 070 071 GenPolynomial<C> S = Ap.copy(); 072 while (S.length() > 0) { 073 if (Pp.size() != ll) { 074 //System.out.println("Pp.size() = " + Pp.size() + ", ll = " + ll); 075 //long t = System.currentTimeMillis(); 076 synchronized (Pp) { 077 Ppp = new ArrayList<GenPolynomial<C>>(Pp); // sic 078 } 079 P = Ppp.toArray(P); 080 ll = Ppp.size(); 081 //ll = P.length; // wrong 082 //t = System.currentTimeMillis()-t; 083 //logger.info("Pp.toArray(): size() = {}, ll = {}", l, ll); 084 S = Ap.copy(); // S.add(R)? // restart reduction ? 085 R = Rz.copy(); 086 } 087 boolean mt = false; 088 Map.Entry<ExpVector, C> m = S.leadingMonomial(); 089 ExpVector e = m.getKey(); 090 C a = m.getValue(); 091 ExpVector f = null; 092 int i; 093 for (i = 0; i < ll; i++) { 094 f = P[i].leadingExpVector(); 095 mt = e.multipleOf(f); 096 if (mt) 097 break; 098 } 099 if (!mt) { 100 //System.out.println("m = " + m); 101 //logger.debug("irred"); 102 //R = R.sum(a, e); 103 //S = S.subtract(a, e); 104 R.doPutToMap(e, a); 105 S.doRemoveFromMap(e, a); 106 //System.out.println(" S = " + S); 107 } else { 108 e = e.subtract(f); 109 //logger.info("red div = {}", e); 110 C c = P[i].leadingBaseCoefficient(); 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. 129 * @param Pp polynomial list. 130 * @param Ap polynomial. 131 * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor 132 * for Ap. 133 */ 134 @SuppressWarnings("unchecked") 135 public PseudoReductionEntry<C> normalformFactor(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 136 if (Ap == null) { 137 return null; 138 } 139 C mfac = Ap.ring.getONECoefficient(); 140 PseudoReductionEntry<C> pf = new PseudoReductionEntry<C>(Ap, mfac); 141 if (Pp == null || Pp.isEmpty()) { 142 return pf; 143 } 144 if (Ap.isZERO()) { 145 return pf; 146 } 147 GenPolynomial<C>[] P = new GenPolynomial[0]; 148 List<GenPolynomial<C>> Ppp; 149 synchronized (Pp) { 150 Ppp = new ArrayList<GenPolynomial<C>>(Pp); // sic 151 } 152 P = Ppp.toArray(P); 153 int l = Ppp.size(); 154 boolean mt = false; 155 GenPolynomial<C> Rz = Ap.ring.getZERO(); 156 GenPolynomial<C> R = Rz.copy(); 157 //GenPolynomial<C> T = null; 158 //GenPolynomial<C> Q = null; 159 GenPolynomial<C> S = Ap.copy(); 160 while (S.length() > 0) { 161 if (Pp.size() != l) { 162 //long t = System.currentTimeMillis(); 163 synchronized (Pp) { 164 Ppp = new ArrayList<GenPolynomial<C>>(Pp); 165 } 166 P = Ppp.toArray(P); 167 l = Ppp.size(); 168 //t = System.currentTimeMillis()-t; 169 //logger.info("Pp.toArray() = {} ms, size() = {}", t, l); 170 S = Ap.copy(); // S.add(R)? // restart reduction ? 171 R = Rz.copy(); 172 } 173 Map.Entry<ExpVector, C> m = S.leadingMonomial(); 174 ExpVector e = m.getKey(); 175 C a = m.getValue(); 176 ExpVector f = null; 177 int i; 178 for (i = 0; i < l; i++) { 179 f = P[i].leadingExpVector(); 180 mt = e.multipleOf(f); 181 if (mt) 182 break; 183 } 184 if (!mt) { 185 //logger.debug("irred"); 186 //R = R.sum(a, e); 187 //S = S.subtract(a, e); 188 R.doPutToMap(e, a); 189 S.doRemoveFromMap(e, a); 190 //System.out.println(" S = " + S); 191 } else { 192 e = e.subtract(f); 193 //logger.info("red div = {}", e); 194 C c = P[i].leadingBaseCoefficient(); 195 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 196 a = a.divide(c); 197 S = S.subtractMultiple(a, e, P[i]); 198 } else { 199 mfac = mfac.multiply(c); 200 R = R.multiply(c); 201 //S = S.multiply(c); 202 S = S.scaleSubtractMultiple(c, a, e, P[i]); 203 } 204 //Q = p[i].multiply(a, e); 205 //S = S.subtract(Q); 206 } 207 } 208 logger.info("multiplicative factor = {}", mfac); 209 pf = new PseudoReductionEntry<C>(R, mfac); 210 return pf; 211 } 212 213 214 /** 215 * Normalform with recording. <b>Note:</b> Only meaningful if all divisions 216 * are exact. Compute first the multiplication factor <code>m</code> with 217 * <code>normalform(Pp,Ap,m)</code>, then call this method with 218 * <code>normalform(row,Pp,m*Ap)</code>. 219 * @param row recording matrix, is modified. 220 * @param Pp a polynomial list for reduction. 221 * @param Ap a polynomial. 222 * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. 223 */ 224 @SuppressWarnings("unchecked") 225 public GenPolynomial<C> normalform(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp, 226 GenPolynomial<C> Ap) { 227 throw new RuntimeException("normalform with recording not implemented"); 228 } 229 230 231 /** 232 * Normalform recursive. 233 * @param Ap recursive polynomial. 234 * @param Pp recursive polynomial list. 235 * @return nf(Ap) with respect to Pp. 236 */ 237 @SuppressWarnings("unchecked") 238 public GenPolynomial<GenPolynomial<C>> normalformRecursive(List<GenPolynomial<GenPolynomial<C>>> Pp, GenPolynomial<GenPolynomial<C>> Ap) { 239 if (Pp == null || Pp.isEmpty()) { 240 return Ap; 241 } 242 if (Ap == null || Ap.isZERO()) { 243 return Ap; 244 } 245 GenPolynomial<GenPolynomial<C>>[] P = new GenPolynomial[0]; 246 List<GenPolynomial<GenPolynomial<C>>> Ppp; 247 synchronized (Pp) { 248 Ppp = new ArrayList<GenPolynomial<GenPolynomial<C>>>(Pp); // sic 249 } 250 P = Ppp.toArray(P); 251 int ll = Ppp.size(); 252 GenPolynomial<GenPolynomial<C>> Rz = Ap.ring.getZERO(); 253 GenPolynomial<GenPolynomial<C>> R = Rz.copy(); 254 255 GenPolynomial<GenPolynomial<C>> S = Ap.copy(); 256 while (S.length() > 0) { 257 if (Pp.size() != ll) { 258 //System.out.println("Pp.size() = " + Pp.size() + ", ll = " + ll); 259 //long t = System.currentTimeMillis(); 260 synchronized (Pp) { 261 Ppp = new ArrayList<GenPolynomial<GenPolynomial<C>>>(Pp); // sic 262 } 263 P = Ppp.toArray(P); 264 ll = Ppp.size(); 265 //ll = P.length; // wrong 266 //t = System.currentTimeMillis()-t; 267 //logger.info("Pp.toArray(): size() = {}, ll = {}", l, ll); 268 S = Ap.copy(); // S.add(R)? // restart reduction ? 269 R = Rz.copy(); 270 } 271 boolean mt = false; 272 Map.Entry<ExpVector, GenPolynomial<C>> m = S.leadingMonomial(); 273 ExpVector e = m.getKey(); 274 GenPolynomial<C> a = m.getValue(); 275 ExpVector f = null; 276 int i; 277 for (i = 0; i < ll; i++) { 278 f = P[i].leadingExpVector(); 279 mt = e.multipleOf(f); 280 if (mt) 281 break; 282 } 283 if (!mt) { 284 //System.out.println("m = " + m); 285 //logger.debug("irred"); 286 //R = R.sum(a, e); 287 //S = S.subtract(a, e); 288 R.doPutToMap(e, a); 289 S.doRemoveFromMap(e, a); 290 //System.out.println(" S = " + S); 291 } else { 292 f = e.subtract(f); 293 if (debug) { 294 logger.info("red div = {}", e); 295 } 296 GenPolynomial<C> c = P[i].leadingBaseCoefficient(); 297 //if (a.remainder(c).isZERO()) { //c.isUnit() ) { 298 if (PolyUtil.<C> baseSparsePseudoRemainder(a,c).isZERO()) { 299 if (debug) { 300 logger.info("red c = {}", c); 301 } 302 //a = a.divide(c); 303 GenPolynomial<C> b = PolyUtil.<C> basePseudoDivide(a,c); 304 GenPolynomial<GenPolynomial<C>> Sp = S.subtractMultiple(b, f, P[i]); 305 if (e.equals(Sp.leadingExpVector())) { // TODO: avoid if possible 306 //throw new RuntimeException("degree not descending"); 307 logger.info("degree not descending: S = {}, Sp = {}", S, Sp); 308 R = R.multiply(c); 309 //S = S.multiply(c); 310 Sp = S.scaleSubtractMultiple(c, a, f, P[i]); 311 } 312 S = Sp; 313 } else { 314 R = R.multiply(c); 315 //S = S.multiply(c); 316 S = S.scaleSubtractMultiple(c, a, f, P[i]); 317 } 318 //Q = p[i].multiply(a, f); 319 //S = S.subtract(Q); 320 } 321 } 322 return R; 323 } 324 325}