001/* 002 * $Id: GreatestCommonDivisorSimple.java 5774 2017-11-05 17:04:30Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import org.apache.log4j.Logger; 009 010import edu.jas.poly.GenPolynomial; 011import edu.jas.poly.PolyUtil; 012import edu.jas.structure.GcdRingElem; 013import edu.jas.structure.RingFactory; 014 015 016/** 017 * Greatest common divisor algorithms with monic polynomial remainder sequence. 018 * If C is a field, then the monic PRS (on coefficients) is computed otherwise 019 * no simplifications in the reduction are made. 020 * @author Heinz Kredel 021 */ 022 023public class GreatestCommonDivisorSimple<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> { 024 025 026 private static final Logger logger = Logger.getLogger(GreatestCommonDivisorSimple.class); 027 028 029 private static final boolean debug = logger.isDebugEnabled(); 030 031 032 /** 033 * Univariate GenPolynomial greatest comon divisor. Uses pseudoRemainder for 034 * remainder. 035 * @param P univariate GenPolynomial. 036 * @param S univariate GenPolynomial. 037 * @return gcd(P,S). 038 */ 039 @Override 040 public GenPolynomial<C> baseGcd(GenPolynomial<C> P, GenPolynomial<C> S) { 041 if (S == null || S.isZERO()) { 042 return P; 043 } 044 if (P == null || P.isZERO()) { 045 return S; 046 } 047 if (P.ring.nvar > 1) { 048 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 049 } 050 boolean field = P.ring.coFac.isField(); 051 long e = P.degree(0); 052 long f = S.degree(0); 053 GenPolynomial<C> q; 054 GenPolynomial<C> r; 055 if (f > e) { 056 r = P; 057 q = S; 058 long g = f; 059 f = e; 060 e = g; 061 } else { 062 q = P; 063 r = S; 064 } 065 if (debug) { 066 logger.debug("degrees: e = " + e + ", f = " + f); 067 } 068 C c; 069 if (field) { 070 r = r.monic(); 071 q = q.monic(); 072 c = P.ring.getONECoefficient(); 073 } else { 074 r = r.abs(); 075 q = q.abs(); 076 C a = baseContent(r); 077 C b = baseContent(q); 078 c = gcd(a, b); // indirection 079 r = divide(r, a); // indirection 080 q = divide(q, b); // indirection 081 } 082 if (r.isONE()) { 083 return r.multiply(c); 084 } 085 if (q.isONE()) { 086 return q.multiply(c); 087 } 088 GenPolynomial<C> x; 089 //System.out.println("q = " + q); 090 //System.out.println("r = " + r); 091 while (!r.isZERO()) { 092 x = PolyUtil.<C> baseSparsePseudoRemainder(q, r); 093 q = r; 094 if (field) { 095 r = x.monic(); 096 } else { 097 r = x; 098 } 099 //System.out.println("q = " + q); 100 //System.out.println("r = " + r); 101 } 102 q = basePrimitivePart(q); 103 return (q.multiply(c)).abs(); 104 } 105 106 107 /** 108 * Univariate GenPolynomial recursive greatest comon divisor. Uses 109 * pseudoRemainder for remainder. 110 * @param P univariate recursive GenPolynomial. 111 * @param S univariate recursive GenPolynomial. 112 * @return gcd(P,S). 113 */ 114 @Override 115 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(GenPolynomial<GenPolynomial<C>> P, 116 GenPolynomial<GenPolynomial<C>> S) { 117 if (S == null || S.isZERO()) { 118 return P; 119 } 120 if (P == null || P.isZERO()) { 121 return S; 122 } 123 if (P.ring.nvar > 1) { 124 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 125 } 126 boolean field = P.leadingBaseCoefficient().ring.coFac.isField(); 127 long e = P.degree(0); 128 long f = S.degree(0); 129 GenPolynomial<GenPolynomial<C>> q; 130 GenPolynomial<GenPolynomial<C>> r; 131 if (f > e) { 132 r = P; 133 q = S; 134 long g = f; 135 f = e; 136 e = g; 137 } else { 138 q = P; 139 r = S; 140 } 141 if (debug) { 142 logger.debug("degrees: e = " + e + ", f = " + f); 143 } 144 if (field) { 145 r = PolyUtil.<C> monic(r); 146 q = PolyUtil.<C> monic(q); 147 } else { 148 r = r.abs(); 149 q = q.abs(); 150 } 151 GenPolynomial<C> a = recursiveContent(r); 152 GenPolynomial<C> b = recursiveContent(q); 153 154 GenPolynomial<C> c = gcd(a, b); // go to recursion 155 //System.out.println("rgcd c = " + c); 156 r = PolyUtil.<C> recursiveDivide(r, a); 157 q = PolyUtil.<C> recursiveDivide(q, b); 158 if (r.isONE()) { 159 return r.multiply(c); 160 } 161 if (q.isONE()) { 162 return q.multiply(c); 163 } 164 GenPolynomial<GenPolynomial<C>> x; 165 while (!r.isZERO()) { 166 x = PolyUtil.<C> recursivePseudoRemainder(q, r); 167 if (logger.isDebugEnabled()) { 168 logger.info("recursivePseudoRemainder.bits = " + x.bitLength()); 169 } 170 q = r; 171 if (field) { 172 r = PolyUtil.<C> monic(x); 173 } else { 174 r = x; 175 } 176 } 177 q = recursivePrimitivePart(q); 178 q = q.abs().multiply(c); 179 return q; 180 } 181 182 183 /** 184 * Univariate GenPolynomial resultant. 185 * @param P univariate GenPolynomial. 186 * @param S univariate GenPolynomial. 187 * @return res(P,S). 188 */ 189 @Override 190 public GenPolynomial<C> baseResultant(GenPolynomial<C> P, GenPolynomial<C> S) { 191 if (S == null || S.isZERO()) { 192 return S; 193 } 194 if (P == null || P.isZERO()) { 195 return P; 196 } 197 if (P.ring.nvar > 1 || P.ring.nvar == 0) { 198 throw new IllegalArgumentException("no univariate polynomial"); 199 } 200 long e = P.degree(0); 201 long f = S.degree(0); 202 if (f == 0 && e == 0) { 203 return P.ring.getONE(); 204 } 205 if (e == 0) { 206 return P.power(f); 207 } 208 if (f == 0) { 209 return S.power(e); 210 } 211 GenPolynomial<C> q; 212 GenPolynomial<C> r; 213 int s = 0; // sign is +, 1 for sign is - 214 if (e < f) { 215 r = P; 216 q = S; 217 long t = e; 218 e = f; 219 f = t; 220 if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) 221 s = 1; 222 } 223 } else { 224 q = P; 225 r = S; 226 } 227 RingFactory<C> cofac = P.ring.coFac; 228 boolean field = cofac.isField(); 229 C c = cofac.getONE(); 230 GenPolynomial<C> x; 231 long g; 232 do { 233 if (field) { 234 x = q.remainder(r); 235 } else { 236 x = PolyUtil.<C> baseSparsePseudoRemainder(q, r); 237 //System.out.println("x_s = " + x + ", lbcf(r) = " + r.leadingBaseCoefficient()); 238 } 239 if (x.isZERO()) { 240 return x; 241 } 242 //System.out.println("x = " + x); 243 e = q.degree(0); 244 f = r.degree(0); 245 if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) 246 s = 1 - s; 247 } 248 g = x.degree(0); 249 C c2 = r.leadingBaseCoefficient(); 250 for (int i = 0; i < (e - g); i++) { 251 c = c.multiply(c2); 252 } 253 q = r; 254 r = x; 255 } while (g != 0); 256 C c2 = r.leadingBaseCoefficient(); 257 for (int i = 0; i < f; i++) { 258 c = c.multiply(c2); 259 } 260 if (s == 1) { 261 c = c.negate(); 262 } 263 x = P.ring.getONE().multiply(c); 264 return x; 265 } 266 267 268 /** 269 * Univariate GenPolynomial recursive resultant. 270 * @param P univariate recursive GenPolynomial. 271 * @param S univariate recursive GenPolynomial. 272 * @return res(P,S). 273 */ 274 @Override 275 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(GenPolynomial<GenPolynomial<C>> P, 276 GenPolynomial<GenPolynomial<C>> S) { 277 if (S == null || S.isZERO()) { 278 return S; 279 } 280 if (P == null || P.isZERO()) { 281 return P; 282 } 283 if (P.ring.nvar > 1 || P.ring.nvar == 0) { 284 throw new IllegalArgumentException("no recursive univariate polynomial"); 285 } 286 long e = P.degree(0); 287 long f = S.degree(0); 288 if (f == 0 && e == 0) { 289 // if coeffs are multivariate (and non constant) 290 // otherwise it would be 1 291 GenPolynomial<C> t = resultant(P.leadingBaseCoefficient(), S.leadingBaseCoefficient()); 292 return P.ring.getONE().multiply(t); 293 } 294 if (e == 0) { 295 return P.power(f); 296 } 297 if (f == 0) { 298 return S.power(e); 299 } 300 GenPolynomial<GenPolynomial<C>> q; 301 GenPolynomial<GenPolynomial<C>> r; 302 int s = 0; // sign is +, 1 for sign is - 303 if (f > e) { 304 r = P; 305 q = S; 306 long g = f; 307 f = e; 308 e = g; 309 if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) 310 s = 1; 311 } 312 } else { 313 q = P; 314 r = S; 315 } 316 GenPolynomial<GenPolynomial<C>> x; 317 RingFactory<GenPolynomial<C>> cofac = P.ring.coFac; 318 GenPolynomial<C> c = cofac.getONE(); 319 long g; 320 do { 321 x = PolyUtil.<C> recursiveSparsePseudoRemainder(q, r); 322 //x = PolyUtil.<C>recursiveDensePseudoRemainder(q,r); 323 if (x.isZERO()) { 324 return x; 325 } 326 //no: x = recursivePrimitivePart(x); 327 //System.out.println("x = " + x); 328 e = q.degree(0); 329 f = r.degree(0); 330 if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) 331 s = 1 - s; 332 } 333 g = x.degree(0); 334 GenPolynomial<C> c2 = r.leadingBaseCoefficient(); 335 for (int i = 0; i < (e - g); i++) { 336 c = c.multiply(c2); 337 } 338 q = r; 339 r = x; 340 } while (g != 0); 341 GenPolynomial<C> c2 = r.leadingBaseCoefficient(); 342 for (int i = 0; i < f; i++) { 343 c = c.multiply(c2); 344 } 345 if (s == 1) { 346 c = c.negate(); 347 } 348 x = P.ring.getONE().multiply(c); 349 return x; 350 } 351 352}