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