001/* 002 * $Id$ 003 */ 004 005package edu.jas.application; 006 007 008import java.io.BufferedReader; 009import java.io.IOException; 010import java.io.InputStreamReader; 011import java.io.Reader; 012import java.io.StreamTokenizer; 013import java.nio.charset.Charset; 014import java.util.ArrayList; 015import java.util.Arrays; 016import java.util.Iterator; 017import java.util.List; 018import java.util.Scanner; 019 020import org.apache.logging.log4j.Logger; 021import org.apache.logging.log4j.LogManager; 022 023import edu.jas.arith.BigComplex; 024import edu.jas.arith.BigDecimal; 025import edu.jas.arith.BigInteger; 026import edu.jas.arith.BigQuaternion; 027import edu.jas.arith.BigQuaternionRing; 028import edu.jas.arith.BigRational; 029import edu.jas.arith.ModInteger; 030import edu.jas.arith.ModIntegerRing; 031import edu.jas.arith.ModIntRing; 032import edu.jas.arith.ModLongRing; 033import edu.jas.poly.AlgebraicNumberRing; 034import edu.jas.poly.ExpVector; 035import edu.jas.poly.GenPolynomial; 036import edu.jas.poly.GenPolynomialRing; 037import edu.jas.poly.GenPolynomialTokenizer; 038import edu.jas.poly.GenSolvablePolynomial; 039import edu.jas.poly.GenSolvablePolynomialRing; 040import edu.jas.poly.InvalidExpressionException; 041import edu.jas.poly.RelationTable; 042import edu.jas.poly.TermOrder; 043import edu.jas.structure.RingFactory; 044import edu.jas.ufd.Quotient; 045import edu.jas.ufd.QuotientRing; 046 047 048/** 049 * RingFactory Tokenizer. Used to read ring factories from input streams. It can 050 * also read QuotientRing factory. 051 * @see edu.jas.poly.GenPolynomialTokenizer 052 * @author Heinz Kredel 053 */ 054public class RingFactoryTokenizer { 055 056 057 private static final Logger logger = LogManager.getLogger(RingFactoryTokenizer.class); 058 059 060 private static final boolean debug = logger.isDebugEnabled(); 061 062 063 private String[] vars; 064 065 066 private int nvars = 1; 067 068 069 private TermOrder tord; 070 071 072 private RelationTable table; 073 074 075 private final StreamTokenizer tok; 076 077 078 private final Reader reader; 079 080 081 private RingFactory fac; 082 083 084 private static enum coeffType { 085 BigRat, BigInt, ModInt, BigC, BigQ, BigD, ANrat, ANmod, RatFunc, ModFunc, IntFunc 086 }; 087 088 089 private coeffType parsedCoeff = coeffType.BigRat; 090 091 092 private GenPolynomialRing pfac; 093 094 095 private static enum polyType { 096 PolBigRat, PolBigInt, PolModInt, PolBigC, PolBigD, PolBigQ, PolANrat, PolANmod, PolRatFunc, PolModFunc, PolIntFunc 097 }; 098 099 100 @SuppressWarnings("unused") 101 private polyType parsedPoly = polyType.PolBigRat; 102 103 104 private GenSolvablePolynomialRing spfac; 105 106 107 /** 108 * No-args constructor reads from System.in. 109 */ 110 public RingFactoryTokenizer() { 111 this(new BufferedReader(new InputStreamReader(System.in, Charset.forName("UTF8")))); 112 } 113 114 115 /** 116 * Constructor with Ring and Reader. 117 * @param rf ring factory. 118 * @param r reader stream. 119 */ 120 public RingFactoryTokenizer(GenPolynomialRing rf, Reader r) { 121 this(r); 122 if (rf == null) { 123 return; 124 } 125 if (rf instanceof GenSolvablePolynomialRing) { 126 pfac = rf; 127 spfac = (GenSolvablePolynomialRing) rf; 128 } else { 129 pfac = rf; 130 spfac = null; 131 } 132 fac = rf.coFac; 133 vars = rf.getVars(); 134 if (vars != null) { 135 nvars = vars.length; 136 } 137 tord = rf.tord; 138 // relation table 139 if (spfac != null) { 140 table = spfac.table; 141 } else { 142 table = null; 143 } 144 } 145 146 147 /** 148 * Constructor with Reader. 149 * @param r reader stream. 150 */ 151 @SuppressWarnings("unchecked") 152 public RingFactoryTokenizer(Reader r) { 153 vars = null; 154 tord = new TermOrder(); 155 nvars = 1; 156 fac = new BigRational(1); 157 158 pfac = new GenPolynomialRing<BigRational>(fac, nvars, tord, vars); 159 spfac = new GenSolvablePolynomialRing<BigRational>(fac, nvars, tord, vars); 160 161 reader = r; 162 tok = new StreamTokenizer(reader); 163 tok.resetSyntax(); 164 // tok.eolIsSignificant(true); no more 165 tok.eolIsSignificant(false); 166 tok.wordChars('0', '9'); 167 tok.wordChars('a', 'z'); 168 tok.wordChars('A', 'Z'); 169 tok.wordChars('_', '_'); // for subscripts x_i 170 tok.wordChars('/', '/'); // wg. rational numbers 171 tok.wordChars('.', '.'); // wg. floats 172 tok.wordChars('~', '~'); // wg. quaternions // unused in this class 173 tok.wordChars(128 + 32, 255); 174 tok.whitespaceChars(0, ' '); 175 tok.commentChar('#'); 176 tok.quoteChar('"'); 177 tok.quoteChar('\''); 178 //tok.slashStarComments(true); does not work 179 180 } 181 182 183 /** 184 * Initialize coefficient and polynomial factories. 185 * @param rf ring factory. 186 * @param ct coefficient type. 187 */ 188 @SuppressWarnings("unchecked") 189 public void initFactory(RingFactory rf, coeffType ct) { 190 fac = rf; 191 parsedCoeff = ct; 192 193 switch (ct) { 194 case BigRat: 195 pfac = new GenPolynomialRing<BigRational>(fac, nvars, tord, vars); 196 parsedPoly = polyType.PolBigRat; 197 break; 198 case BigInt: 199 pfac = new GenPolynomialRing<BigInteger>(fac, nvars, tord, vars); 200 parsedPoly = polyType.PolBigInt; 201 break; 202 case ModInt: 203 pfac = new GenPolynomialRing<ModInteger>(fac, nvars, tord, vars); 204 parsedPoly = polyType.PolModInt; 205 break; 206 case BigC: 207 pfac = new GenPolynomialRing<BigComplex>(fac, nvars, tord, vars); 208 parsedPoly = polyType.PolBigC; 209 break; 210 case BigQ: 211 pfac = new GenPolynomialRing<BigQuaternion>(fac, nvars, tord, vars); 212 parsedPoly = polyType.PolBigQ; 213 break; 214 case BigD: 215 pfac = new GenPolynomialRing<BigDecimal>(fac, nvars, tord, vars); 216 parsedPoly = polyType.PolBigD; 217 break; 218 case RatFunc: 219 pfac = new GenPolynomialRing<Quotient<BigInteger>>(fac, nvars, tord, vars); 220 parsedPoly = polyType.PolRatFunc; 221 break; 222 case ModFunc: 223 pfac = new GenPolynomialRing<Quotient<ModInteger>>(fac, nvars, tord, vars); 224 parsedPoly = polyType.PolModFunc; 225 break; 226 case IntFunc: 227 pfac = new GenPolynomialRing<GenPolynomial<BigRational>>(fac, nvars, tord, vars); 228 parsedPoly = polyType.PolIntFunc; 229 break; 230 default: 231 pfac = new GenPolynomialRing<BigRational>(fac, nvars, tord, vars); 232 parsedPoly = polyType.PolBigRat; 233 } 234 } 235 236 237 /** 238 * Initialize coefficient and solvable polynomial factories. 239 * @param rf ring factory. 240 * @param ct coefficient type. 241 */ 242 @SuppressWarnings("unchecked") 243 public void initSolvableFactory(RingFactory rf, coeffType ct) { 244 fac = rf; 245 parsedCoeff = ct; 246 247 switch (ct) { 248 case BigRat: 249 spfac = new GenSolvablePolynomialRing<BigRational>(fac, nvars, tord, vars); 250 parsedPoly = polyType.PolBigRat; 251 break; 252 case BigInt: 253 spfac = new GenSolvablePolynomialRing<BigInteger>(fac, nvars, tord, vars); 254 parsedPoly = polyType.PolBigInt; 255 break; 256 case ModInt: 257 spfac = new GenSolvablePolynomialRing<ModInteger>(fac, nvars, tord, vars); 258 parsedPoly = polyType.PolModInt; 259 break; 260 case BigC: 261 spfac = new GenSolvablePolynomialRing<BigComplex>(fac, nvars, tord, vars); 262 parsedPoly = polyType.PolBigC; 263 break; 264 case BigQ: 265 spfac = new GenSolvablePolynomialRing<BigQuaternion>(fac, nvars, tord, vars); 266 parsedPoly = polyType.PolBigQ; 267 break; 268 case BigD: 269 spfac = new GenSolvablePolynomialRing<BigDecimal>(fac, nvars, tord, vars); 270 parsedPoly = polyType.PolBigD; 271 break; 272 case RatFunc: 273 spfac = new GenSolvablePolynomialRing<Quotient<BigInteger>>(fac, nvars, tord, vars); 274 parsedPoly = polyType.PolRatFunc; 275 break; 276 case ModFunc: 277 spfac = new GenSolvablePolynomialRing<Quotient<ModInteger>>(fac, nvars, tord, vars); 278 parsedPoly = polyType.PolModFunc; 279 break; 280 case IntFunc: 281 spfac = new GenSolvablePolynomialRing<GenPolynomial<BigRational>>(fac, nvars, tord, vars); 282 parsedPoly = polyType.PolIntFunc; 283 break; 284 default: 285 spfac = new GenSolvablePolynomialRing<BigRational>(fac, nvars, tord, vars); 286 parsedPoly = polyType.PolBigRat; 287 } 288 } 289 290 291 /** 292 * Parsing method for variable list. Syntax: 293 * 294 * <pre> 295 * (a, b c, de) 296 * </pre> 297 * 298 * gives <code>[ "a", "b", "c", "de" ]</code> 299 * @return the next variable list. 300 * @throws IOException 301 */ 302 public String[] nextVariableList() throws IOException { 303 List<String> l = new ArrayList<String>(); 304 int tt; 305 tt = tok.nextToken(); 306 //System.out.println("vList tok = " + tok); 307 if (tt == '(' || tt == '{') { 308 logger.debug("variable list"); 309 tt = tok.nextToken(); 310 while (true) { 311 if (tt == StreamTokenizer.TT_EOF) 312 break; 313 if (tt == ')' || tt == '}') 314 break; 315 if (tt == StreamTokenizer.TT_WORD) { 316 //System.out.println("TT_WORD: " + tok.sval); 317 l.add(tok.sval); 318 } 319 tt = tok.nextToken(); 320 } 321 } else { 322 tok.pushBack(); 323 } 324 Object[] ol = l.toArray(); 325 String[] v = new String[ol.length]; 326 for (int i = 0; i < v.length; i++) { 327 v[i] = (String) ol[i]; 328 } 329 return v; 330 } 331 332 333 /** 334 * Parsing method for coefficient ring. Syntax: 335 * 336 * <pre> 337 * Rat | Q | Int | Z | Mod modul | Complex | C | D | Quat | 338 AN[ (var) ( poly ) | AN[ modul (var) ( poly ) ] | 339 RatFunc (var_list) | ModFunc modul (var_list) | IntFunc (var_list) 340 * </pre> 341 * 342 * @return the next coefficient factory. 343 * @throws IOException 344 */ 345 @SuppressWarnings({ "unchecked", "cast" }) 346 public RingFactory nextCoefficientRing() throws IOException { 347 RingFactory coeff = null; 348 coeffType ct = null; 349 int tt; 350 tt = tok.nextToken(); 351 if (tok.sval != null) { 352 if (tok.sval.equalsIgnoreCase("Q")) { 353 coeff = new BigRational(0); 354 ct = coeffType.BigRat; 355 } else if (tok.sval.equalsIgnoreCase("Rat")) { 356 coeff = new BigRational(0); 357 ct = coeffType.BigRat; 358 } else if (tok.sval.equalsIgnoreCase("D")) { 359 coeff = new BigDecimal(0); 360 ct = coeffType.BigD; 361 } else if (tok.sval.equalsIgnoreCase("Z")) { 362 coeff = new BigInteger(0); 363 ct = coeffType.BigInt; 364 } else if (tok.sval.equalsIgnoreCase("Int")) { 365 coeff = new BigInteger(0); 366 ct = coeffType.BigInt; 367 } else if (tok.sval.equalsIgnoreCase("C")) { 368 coeff = new BigComplex(0); 369 ct = coeffType.BigC; 370 } else if (tok.sval.equalsIgnoreCase("Complex")) { 371 coeff = new BigComplex(0); 372 ct = coeffType.BigC; 373 } else if (tok.sval.equalsIgnoreCase("Quat")) { 374 logger.warn("parse of quaternion coefficients may fail for negative components (use ~ for -)"); 375 coeff = new BigQuaternionRing(); 376 ct = coeffType.BigQ; 377 } else if (tok.sval.equalsIgnoreCase("Mod")) { 378 tt = tok.nextToken(); 379 boolean openb = false; 380 if (tt == '[') { // optional 381 openb = true; 382 tt = tok.nextToken(); 383 } 384 if (tok.sval != null && tok.sval.length() > 0) { 385 if (digit(tok.sval.charAt(0))) { 386 BigInteger mo = new BigInteger(tok.sval); 387 BigInteger lm = new BigInteger(ModLongRing.MAX_LONG); //wrong: Long.MAX_VALUE); 388 if (mo.compareTo(lm) < 0) { 389 if (mo.compareTo(new BigInteger(ModIntRing.MAX_INT)) < 0) { 390 coeff = new ModIntRing(mo.getVal()); 391 } else { 392 coeff = new ModLongRing(mo.getVal()); 393 } 394 } else { 395 coeff = new ModIntegerRing(mo.getVal()); 396 } 397 //System.out.println("coeff = " + coeff + " :: " + coeff.getClass()); 398 ct = coeffType.ModInt; 399 } else { 400 tok.pushBack(); 401 } 402 } else { 403 tok.pushBack(); 404 } 405 if (tt == ']' && openb) { // optional 406 tt = tok.nextToken(); 407 } 408 } else if (tok.sval.equalsIgnoreCase("RatFunc")) { 409 String[] rfv = nextVariableList(); 410 //System.out.println("rfv = " + rfv.length + " " + rfv[0]); 411 int vr = rfv.length; 412 BigInteger bi = new BigInteger(); 413 TermOrder to = new TermOrder(TermOrder.INVLEX); 414 GenPolynomialRing<BigInteger> pcf = new GenPolynomialRing<BigInteger>(bi, vr, to, rfv); 415 coeff = new QuotientRing(pcf); 416 ct = coeffType.RatFunc; 417 } else if (tok.sval.equalsIgnoreCase("ModFunc")) { 418 tt = tok.nextToken(); 419 RingFactory mi = new ModIntegerRing("19"); 420 if (tok.sval != null && tok.sval.length() > 0) { 421 if (digit(tok.sval.charAt(0))) { 422 mi = new ModIntegerRing(tok.sval); 423 } else { 424 tok.pushBack(); 425 } 426 } else { 427 tok.pushBack(); 428 } 429 String[] rfv = nextVariableList(); 430 //System.out.println("rfv = " + rfv.length + " " + rfv[0]); 431 int vr = rfv.length; 432 TermOrder to = new TermOrder(TermOrder.INVLEX); 433 GenPolynomialRing<ModInteger> pcf = new GenPolynomialRing<ModInteger>(mi, vr, to, rfv); 434 coeff = new QuotientRing(pcf); 435 ct = coeffType.ModFunc; 436 } else if (tok.sval.equalsIgnoreCase("IntFunc")) { 437 String[] rfv = nextVariableList(); 438 //System.out.println("rfv = " + rfv.length + " " + rfv[0]); 439 int vr = rfv.length; 440 BigRational bi = new BigRational(); 441 TermOrder to = new TermOrder(TermOrder.INVLEX); 442 GenPolynomialRing<BigRational> pcf = new GenPolynomialRing<BigRational>(bi, vr, to, rfv); 443 coeff = pcf; 444 ct = coeffType.IntFunc; 445 } else if (tok.sval.equalsIgnoreCase("AN")) { 446 tt = tok.nextToken(); 447 if (tt == '[') { 448 tt = tok.nextToken(); 449 RingFactory tcfac = new ModIntegerRing("19"); 450 if (tok.sval != null && tok.sval.length() > 0) { 451 if (digit(tok.sval.charAt(0))) { 452 tcfac = new ModIntegerRing(tok.sval); 453 } else { 454 tcfac = new BigRational(); 455 tok.pushBack(); 456 } 457 } else { 458 tcfac = new BigRational(); 459 tok.pushBack(); 460 } 461 String[] anv = nextVariableList(); 462 //System.out.println("anv = " + anv.length + " " + anv[0]); 463 int vs = anv.length; 464 if (vs != 1) { 465 throw new InvalidExpressionException( 466 "AlgebraicNumber only for univariate polynomials " 467 + Arrays.toString(anv)); 468 } 469 String[] ovars = vars; 470 vars = anv; 471 GenPolynomialRing tpfac = pfac; 472 RingFactory tfac = fac; 473 fac = tcfac; 474 // pfac and fac used in nextPolynomial() 475 if (tcfac instanceof ModIntegerRing) { 476 pfac = new GenPolynomialRing<ModInteger>(tcfac, vs, new TermOrder(), anv); 477 } else { 478 pfac = new GenPolynomialRing<BigRational>(tcfac, vs, new TermOrder(), anv); 479 } 480 logger.debug("pfac = {}", pfac); 481 GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac, reader); 482 GenPolynomial mod = ptok.nextPolynomial(); 483 ptok = null; 484 logger.debug("mod = {}", mod); 485 pfac = tpfac; 486 fac = tfac; 487 vars = ovars; 488 if (tcfac instanceof ModIntegerRing) { 489 GenPolynomial<ModInteger> gfmod; 490 gfmod = (GenPolynomial<ModInteger>) mod; 491 coeff = new AlgebraicNumberRing<ModInteger>(gfmod); 492 ct = coeffType.ANmod; 493 } else { 494 GenPolynomial<BigRational> anmod; 495 anmod = (GenPolynomial<BigRational>) mod; 496 coeff = new AlgebraicNumberRing<BigRational>(anmod); 497 ct = coeffType.ANrat; 498 } 499 logger.debug("coeff = {}", coeff); 500 tt = tok.nextToken(); 501 if (tt == ']') { 502 //ok, no nextToken(); 503 } else { 504 tok.pushBack(); 505 } 506 } else { 507 tok.pushBack(); 508 } 509 } 510 } 511 if (coeff == null) { 512 tok.pushBack(); 513 coeff = new BigRational(); 514 ct = coeffType.BigRat; 515 } 516 parsedCoeff = ct; 517 return coeff; 518 } 519 520 521 /** 522 * Parsing method for weight list. Syntax: 523 * 524 * <pre> 525 * (w1, w2, w3, ..., wn) 526 * </pre> 527 * 528 * @return the next weight list. 529 * @throws IOException 530 */ 531 public long[] nextWeightList() throws IOException { 532 List<Long> l = new ArrayList<Long>(); 533 long e; 534 char first; 535 int tt; 536 tt = tok.nextToken(); 537 if (tt == '(') { 538 logger.debug("weight list"); 539 tt = tok.nextToken(); 540 while (true) { 541 if (tt == StreamTokenizer.TT_EOF) 542 break; 543 if (tt == ')') 544 break; 545 if (tok.sval != null) { 546 first = tok.sval.charAt(0); 547 if (digit(first)) { 548 e = Long.parseLong(tok.sval); 549 l.add(Long.valueOf(e)); 550 //System.out.println("w: " + e); 551 } 552 } 553 tt = tok.nextToken(); // also comma 554 } 555 } else { 556 tok.pushBack(); 557 } 558 Long[] ol = new Long[1]; 559 ol = l.toArray(ol); 560 long[] w = new long[ol.length]; 561 for (int i = 0; i < w.length; i++) { 562 w[i] = ol[ol.length - i - 1].longValue(); 563 } 564 return w; 565 } 566 567 568 /** 569 * Parsing method for weight array. Syntax: 570 * 571 * <pre> 572 * ( (w11, ...,w1n), ..., (wm1, ..., wmn) ) 573 * </pre> 574 * 575 * @return the next weight array. 576 * @throws IOException 577 */ 578 public long[][] nextWeightArray() throws IOException { 579 List<long[]> l = new ArrayList<long[]>(); 580 long[][] w = null; 581 long[] e; 582 char first; 583 int tt; 584 tt = tok.nextToken(); 585 if (tt == '(') { 586 logger.debug("weight array"); 587 tt = tok.nextToken(); 588 while (true) { 589 if (tt == StreamTokenizer.TT_EOF) 590 break; 591 if (tt == ')') 592 break; 593 if (tt == '(') { 594 tok.pushBack(); 595 e = nextWeightList(); 596 l.add(e); 597 //System.out.println("wa: " + e); 598 } else if (tok.sval != null) { 599 first = tok.sval.charAt(0); 600 if (digit(first)) { 601 tok.pushBack(); 602 tok.pushBack(); 603 e = nextWeightList(); 604 l.add(e); 605 break; 606 //System.out.println("w: " + e); 607 } 608 } 609 tt = tok.nextToken(); // also comma 610 } 611 } else { 612 tok.pushBack(); 613 } 614 Object[] ol = l.toArray(); 615 w = new long[ol.length][]; 616 for (int i = 0; i < w.length; i++) { 617 w[i] = (long[]) ol[i]; 618 } 619 return w; 620 } 621 622 623 /** 624 * Parsing method for split index. Syntax: 625 * 626 * <pre> 627 * |i| 628 * </pre> 629 * 630 * @return the next split index. 631 * @throws IOException 632 */ 633 public int nextSplitIndex() throws IOException { 634 int e = -1; // =unknown 635 int e0 = -1; // =unknown 636 char first; 637 int tt; 638 tt = tok.nextToken(); 639 if (tt == '|') { 640 logger.debug("split index"); 641 tt = tok.nextToken(); 642 if (tt == StreamTokenizer.TT_EOF) { 643 return e; 644 } 645 if (tok.sval != null) { 646 first = tok.sval.charAt(0); 647 if (digit(first)) { 648 e = Integer.parseInt(tok.sval); 649 //System.out.println("w: " + i); 650 } 651 tt = tok.nextToken(); 652 if (tt != '|') { 653 tok.pushBack(); 654 } 655 } 656 } else if (tt == '[') { 657 logger.debug("split index"); 658 tt = tok.nextToken(); 659 if (tt == StreamTokenizer.TT_EOF) { 660 return e; 661 } 662 if (tok.sval != null) { 663 first = tok.sval.charAt(0); 664 if (digit(first)) { 665 e0 = Integer.parseInt(tok.sval); 666 //System.out.println("w: " + i); 667 } 668 tt = tok.nextToken(); 669 if (tt == ',') { 670 tt = tok.nextToken(); 671 if (tt == StreamTokenizer.TT_EOF) { 672 return e0; 673 } 674 if (tok.sval != null) { 675 first = tok.sval.charAt(0); 676 if (digit(first)) { 677 e = Integer.parseInt(tok.sval); 678 //System.out.println("w: " + i); 679 } 680 } 681 if (tt != ']') { 682 tok.pushBack(); 683 } 684 } 685 } 686 } else { 687 tok.pushBack(); 688 } 689 return e; 690 } 691 692 693 /** 694 * Parsing method for term order name. Syntax: 695 * 696 * <pre> 697 * L | IL | LEX | G | IG | GRLEX | W(weights) | '|'split index'|' 698 * </pre> 699 * 700 * @return the next term order. 701 * @throws IOException 702 */ 703 public TermOrder nextTermOrder() throws IOException { 704 int evord = TermOrder.DEFAULT_EVORD; 705 int tt; 706 tt = tok.nextToken(); 707 if (tt == StreamTokenizer.TT_EOF) { /* nop */ 708 } else if (tt == StreamTokenizer.TT_WORD) { 709 // System.out.println("TT_WORD: " + tok.sval); 710 if (tok.sval != null) { 711 if (tok.sval.equalsIgnoreCase("L")) { 712 evord = TermOrder.INVLEX; 713 } else if (tok.sval.equalsIgnoreCase("IL")) { 714 evord = TermOrder.INVLEX; 715 } else if (tok.sval.equalsIgnoreCase("INVLEX")) { 716 evord = TermOrder.INVLEX; 717 } else if (tok.sval.equalsIgnoreCase("LEX")) { 718 evord = TermOrder.LEX; 719 } else if (tok.sval.equalsIgnoreCase("G")) { 720 evord = TermOrder.IGRLEX; 721 } else if (tok.sval.equalsIgnoreCase("IG")) { 722 evord = TermOrder.IGRLEX; 723 } else if (tok.sval.equalsIgnoreCase("IGRLEX")) { 724 evord = TermOrder.IGRLEX; 725 } else if (tok.sval.equalsIgnoreCase("GRLEX")) { 726 evord = TermOrder.GRLEX; 727 } else if (tok.sval.equalsIgnoreCase("REVITDG")) { 728 evord = TermOrder.REVITDG; 729 } else if (tok.sval.equalsIgnoreCase("W")) { 730 long[][] w = nextWeightArray(); 731 return new TermOrder(w); 732 } 733 } 734 } else { 735 tok.pushBack(); 736 } 737 int s = nextSplitIndex(); 738 if (s <= 0) { 739 return new TermOrder(evord); 740 } 741 return new TermOrder(evord, evord, nvars, s); 742 } 743 744 745 /** 746 * Parsing method for solvable polynomial relation table. Syntax: 747 * 748 * <pre> 749 * ( p_1, p_2, p_3, ..., p_{n+1}, p_{n+2}, p_{n+3} ) 750 * </pre> 751 * 752 * semantics: <code>p_{n+1} * p_{n+2} = p_{n+3}</code>. The next relation 753 * table is stored into the solvable polynomial factory. 754 * @throws IOException 755 */ 756 @SuppressWarnings("unchecked") 757 public void nextRelationTable() throws IOException { 758 if (spfac == null) { 759 return; 760 } 761 RelationTable table = spfac.table; 762 List<GenPolynomial> rels = null; 763 GenPolynomial p; 764 GenSolvablePolynomial sp; 765 int tt; 766 tt = tok.nextToken(); 767 logger.debug("start relation table: {}", tt); 768 if (tok.sval != null) { 769 if (tok.sval.equalsIgnoreCase("RelationTable")) { 770 GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac, reader); 771 rels = ptok.nextPolynomialList(); 772 ptok = null; 773 } 774 } 775 if (rels == null) { 776 tok.pushBack(); 777 return; 778 } 779 for (Iterator<GenPolynomial> it = rels.iterator(); it.hasNext();) { 780 p = it.next(); 781 ExpVector e = p.leadingExpVector(); 782 if (it.hasNext()) { 783 p = it.next(); 784 ExpVector f = p.leadingExpVector(); 785 if (it.hasNext()) { 786 p = it.next(); 787 sp = new GenSolvablePolynomial(spfac); 788 sp.doPutToMap(p.getMap()); 789 table.update(e, f, sp); 790 } 791 } 792 } 793 if (debug) { 794 logger.info("table = {}", table); 795 } 796 return; 797 } 798 799 800 /** 801 * Parsing method for polynomial ring. Syntax: 802 * 803 * <pre> 804 * coeffRing varList termOrderName polyList 805 * </pre> 806 * 807 * @return the next polynomial ring. 808 * @throws IOException 809 */ 810 @SuppressWarnings("unchecked") 811 public GenPolynomialRing nextPolynomialRing() throws IOException { 812 //String comments = ""; 813 //comments += nextComment(); 814 //if (debug) logger.debug("comment = {}", comments); 815 816 RingFactory coeff = nextCoefficientRing(); 817 logger.info("coeff = {}", coeff); 818 819 vars = nextVariableList(); 820 final var vv = vars; 821 logger.info("vars = {}", () -> Arrays.toString(vv)); 822 if (vars != null) { 823 nvars = vars.length; 824 } 825 826 tord = nextTermOrder(); 827 logger.info("tord = {}", tord); 828 // check more TOs 829 830 initFactory(coeff, parsedCoeff); // global: nvars, tord, vars 831 // now pfac is initialized 832 return pfac; 833 } 834 835 836 /** 837 * Parsing method for solvable polynomial ring. Syntax: 838 * 839 * <pre> 840 * varList termOrderName relationTable polyList 841 * </pre> 842 * 843 * @return the next solvable polynomial ring. 844 * @throws IOException 845 */ 846 @SuppressWarnings("unchecked") 847 public GenSolvablePolynomialRing nextSolvablePolynomialRing() throws IOException { 848 //String comments = ""; 849 //comments += nextComment(); 850 //if (debug) logger.debug("comment = {}", comments); 851 852 RingFactory coeff = nextCoefficientRing(); 853 logger.info("coeff = {}", coeff.getClass().getSimpleName()); 854 855 vars = nextVariableList(); 856 logger.info("vars = {}", Arrays.toString(vars)); 857 if (vars != null) { 858 nvars = vars.length; 859 } 860 861 tord = nextTermOrder(); 862 logger.info("tord = {}", tord); 863 // check more TOs 864 865 initFactory(coeff, parsedCoeff); // must be because of symmetric read 866 initSolvableFactory(coeff, parsedCoeff); // global: nvars, tord, vars 867 //System.out.println("pfac = " + pfac); 868 //System.out.println("spfac = " + spfac); 869 870 nextRelationTable(); 871 if (logger.isInfoEnabled()) { 872 logger.info("table = {}", table + ", tok = {}", tok); 873 } 874 // now spfac is initialized 875 return spfac; 876 } 877 878 879 static boolean digit(char x) { 880 return '0' <= x && x <= '9'; 881 } 882 883 884 //static boolean letter(char x) { 885 // return ('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z'); 886 //} 887 888 889 // unused 890 public void nextComma() throws IOException { 891 int tt; 892 if (tok.ttype == ',') { 893 tt = tok.nextToken(); 894 if (debug) { 895 logger.debug("after comma: {}", tt); 896 } 897 } 898 } 899 900 901 /** 902 * Parse variable list from String. 903 * @param s String. Syntax: 904 * 905 * <pre> 906 * (n1,...,nk) 907 * </pre> 908 * 909 * or 910 * 911 * <pre> 912 * (n1 ... nk) 913 * </pre> 914 * 915 * parenthesis are optional. 916 * @return array of variable names found in s. 917 */ 918 public static String[] variableList(String s) { 919 String[] vl = null; 920 if (s == null) { 921 return vl; 922 } 923 String st = s.trim(); 924 if (st.length() == 0) { 925 return new String[0]; 926 } 927 if (st.charAt(0) == '(') { 928 st = st.substring(1); 929 } 930 if (st.charAt(st.length() - 1) == ')') { 931 st = st.substring(0, st.length() - 1); 932 } 933 st = st.replaceAll(",", " "); 934 List<String> sl = new ArrayList<String>(); 935 Scanner sc = new Scanner(st); 936 while (sc.hasNext()) { 937 String sn = sc.next(); 938 sl.add(sn); 939 } 940 sc.close(); 941 vl = new String[sl.size()]; 942 int i = 0; 943 for (String si : sl) { 944 vl[i] = si; 945 i++; 946 } 947 return vl; 948 } 949 950}