001/* 002 * $Id: RingFactoryTokenizer.java 5924 2018-09-17 21:38:08Z 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.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 if (debug) { 481 logger.debug("pfac = " + pfac); 482 } 483 GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac, reader); 484 GenPolynomial mod = ptok.nextPolynomial(); 485 ptok = null; 486 if (debug) { 487 logger.debug("mod = " + mod); 488 } 489 pfac = tpfac; 490 fac = tfac; 491 vars = ovars; 492 if (tcfac instanceof ModIntegerRing) { 493 GenPolynomial<ModInteger> gfmod; 494 gfmod = (GenPolynomial<ModInteger>) mod; 495 coeff = new AlgebraicNumberRing<ModInteger>(gfmod); 496 ct = coeffType.ANmod; 497 } else { 498 GenPolynomial<BigRational> anmod; 499 anmod = (GenPolynomial<BigRational>) mod; 500 coeff = new AlgebraicNumberRing<BigRational>(anmod); 501 ct = coeffType.ANrat; 502 } 503 if (debug) { 504 logger.debug("coeff = " + coeff); 505 } 506 tt = tok.nextToken(); 507 if (tt == ']') { 508 //ok, no nextToken(); 509 } else { 510 tok.pushBack(); 511 } 512 } else { 513 tok.pushBack(); 514 } 515 } 516 } 517 if (coeff == null) { 518 tok.pushBack(); 519 coeff = new BigRational(); 520 ct = coeffType.BigRat; 521 } 522 parsedCoeff = ct; 523 return coeff; 524 } 525 526 527 /** 528 * Parsing method for weight list. Syntax: 529 * 530 * <pre> 531 * (w1, w2, w3, ..., wn) 532 * </pre> 533 * 534 * @return the next weight list. 535 * @throws IOException 536 */ 537 public long[] nextWeightList() throws IOException { 538 List<Long> l = new ArrayList<Long>(); 539 long e; 540 char first; 541 int tt; 542 tt = tok.nextToken(); 543 if (tt == '(') { 544 logger.debug("weight list"); 545 tt = tok.nextToken(); 546 while (true) { 547 if (tt == StreamTokenizer.TT_EOF) 548 break; 549 if (tt == ')') 550 break; 551 if (tok.sval != null) { 552 first = tok.sval.charAt(0); 553 if (digit(first)) { 554 e = Long.parseLong(tok.sval); 555 l.add(Long.valueOf(e)); 556 //System.out.println("w: " + e); 557 } 558 } 559 tt = tok.nextToken(); // also comma 560 } 561 } else { 562 tok.pushBack(); 563 } 564 Long[] ol = new Long[1]; 565 ol = l.toArray(ol); 566 long[] w = new long[ol.length]; 567 for (int i = 0; i < w.length; i++) { 568 w[i] = ol[ol.length - i - 1].longValue(); 569 } 570 return w; 571 } 572 573 574 /** 575 * Parsing method for weight array. Syntax: 576 * 577 * <pre> 578 * ( (w11, ...,w1n), ..., (wm1, ..., wmn) ) 579 * </pre> 580 * 581 * @return the next weight array. 582 * @throws IOException 583 */ 584 public long[][] nextWeightArray() throws IOException { 585 List<long[]> l = new ArrayList<long[]>(); 586 long[][] w = null; 587 long[] e; 588 char first; 589 int tt; 590 tt = tok.nextToken(); 591 if (tt == '(') { 592 logger.debug("weight array"); 593 tt = tok.nextToken(); 594 while (true) { 595 if (tt == StreamTokenizer.TT_EOF) 596 break; 597 if (tt == ')') 598 break; 599 if (tt == '(') { 600 tok.pushBack(); 601 e = nextWeightList(); 602 l.add(e); 603 //System.out.println("wa: " + e); 604 } else if (tok.sval != null) { 605 first = tok.sval.charAt(0); 606 if (digit(first)) { 607 tok.pushBack(); 608 tok.pushBack(); 609 e = nextWeightList(); 610 l.add(e); 611 break; 612 //System.out.println("w: " + e); 613 } 614 } 615 tt = tok.nextToken(); // also comma 616 } 617 } else { 618 tok.pushBack(); 619 } 620 Object[] ol = l.toArray(); 621 w = new long[ol.length][]; 622 for (int i = 0; i < w.length; i++) { 623 w[i] = (long[]) ol[i]; 624 } 625 return w; 626 } 627 628 629 /** 630 * Parsing method for split index. Syntax: 631 * 632 * <pre> 633 * |i| 634 * </pre> 635 * 636 * @return the next split index. 637 * @throws IOException 638 */ 639 public int nextSplitIndex() throws IOException { 640 int e = -1; // =unknown 641 int e0 = -1; // =unknown 642 char first; 643 int tt; 644 tt = tok.nextToken(); 645 if (tt == '|') { 646 if (debug) { 647 logger.debug("split index"); 648 } 649 tt = tok.nextToken(); 650 if (tt == StreamTokenizer.TT_EOF) { 651 return e; 652 } 653 if (tok.sval != null) { 654 first = tok.sval.charAt(0); 655 if (digit(first)) { 656 e = Integer.parseInt(tok.sval); 657 //System.out.println("w: " + i); 658 } 659 tt = tok.nextToken(); 660 if (tt != '|') { 661 tok.pushBack(); 662 } 663 } 664 } else if (tt == '[') { 665 if (debug) { 666 logger.debug("split index"); 667 } 668 tt = tok.nextToken(); 669 if (tt == StreamTokenizer.TT_EOF) { 670 return e; 671 } 672 if (tok.sval != null) { 673 first = tok.sval.charAt(0); 674 if (digit(first)) { 675 e0 = Integer.parseInt(tok.sval); 676 //System.out.println("w: " + i); 677 } 678 tt = tok.nextToken(); 679 if (tt == ',') { 680 tt = tok.nextToken(); 681 if (tt == StreamTokenizer.TT_EOF) { 682 return e0; 683 } 684 if (tok.sval != null) { 685 first = tok.sval.charAt(0); 686 if (digit(first)) { 687 e = Integer.parseInt(tok.sval); 688 //System.out.println("w: " + i); 689 } 690 } 691 if (tt != ']') { 692 tok.pushBack(); 693 } 694 } 695 } 696 } else { 697 tok.pushBack(); 698 } 699 return e; 700 } 701 702 703 /** 704 * Parsing method for term order name. Syntax: 705 * 706 * <pre> 707 * L | IL | LEX | G | IG | GRLEX | W(weights) | '|'split index'|' 708 * </pre> 709 * 710 * @return the next term order. 711 * @throws IOException 712 */ 713 public TermOrder nextTermOrder() throws IOException { 714 int evord = TermOrder.DEFAULT_EVORD; 715 int tt; 716 tt = tok.nextToken(); 717 if (tt == StreamTokenizer.TT_EOF) { /* nop */ 718 } else if (tt == StreamTokenizer.TT_WORD) { 719 // System.out.println("TT_WORD: " + tok.sval); 720 if (tok.sval != null) { 721 if (tok.sval.equalsIgnoreCase("L")) { 722 evord = TermOrder.INVLEX; 723 } else if (tok.sval.equalsIgnoreCase("IL")) { 724 evord = TermOrder.INVLEX; 725 } else if (tok.sval.equalsIgnoreCase("INVLEX")) { 726 evord = TermOrder.INVLEX; 727 } else if (tok.sval.equalsIgnoreCase("LEX")) { 728 evord = TermOrder.LEX; 729 } else if (tok.sval.equalsIgnoreCase("G")) { 730 evord = TermOrder.IGRLEX; 731 } else if (tok.sval.equalsIgnoreCase("IG")) { 732 evord = TermOrder.IGRLEX; 733 } else if (tok.sval.equalsIgnoreCase("IGRLEX")) { 734 evord = TermOrder.IGRLEX; 735 } else if (tok.sval.equalsIgnoreCase("GRLEX")) { 736 evord = TermOrder.GRLEX; 737 } else if (tok.sval.equalsIgnoreCase("REVITDG")) { 738 evord = TermOrder.REVITDG; 739 } else if (tok.sval.equalsIgnoreCase("W")) { 740 long[][] w = nextWeightArray(); 741 return new TermOrder(w); 742 } 743 } 744 } else { 745 tok.pushBack(); 746 } 747 int s = nextSplitIndex(); 748 if (s <= 0) { 749 return new TermOrder(evord); 750 } 751 return new TermOrder(evord, evord, nvars, s); 752 } 753 754 755 /** 756 * Parsing method for solvable polynomial relation table. Syntax: 757 * 758 * <pre> 759 * ( p_1, p_2, p_3, ..., p_{n+1}, p_{n+2}, p_{n+3} ) 760 * </pre> 761 * 762 * semantics: <code>p_{n+1} * p_{n+2} = p_{n+3}</code>. The next relation 763 * table is stored into the solvable polynomial factory. 764 * @throws IOException 765 */ 766 @SuppressWarnings("unchecked") 767 public void nextRelationTable() throws IOException { 768 if (spfac == null) { 769 return; 770 } 771 RelationTable table = spfac.table; 772 List<GenPolynomial> rels = null; 773 GenPolynomial p; 774 GenSolvablePolynomial sp; 775 int tt; 776 tt = tok.nextToken(); 777 if (debug) { 778 logger.debug("start relation table: " + tt); 779 } 780 if (tok.sval != null) { 781 if (tok.sval.equalsIgnoreCase("RelationTable")) { 782 GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac, reader); 783 rels = ptok.nextPolynomialList(); 784 ptok = null; 785 } 786 } 787 if (rels == null) { 788 tok.pushBack(); 789 return; 790 } 791 for (Iterator<GenPolynomial> it = rels.iterator(); it.hasNext();) { 792 p = it.next(); 793 ExpVector e = p.leadingExpVector(); 794 if (it.hasNext()) { 795 p = it.next(); 796 ExpVector f = p.leadingExpVector(); 797 if (it.hasNext()) { 798 p = it.next(); 799 sp = new GenSolvablePolynomial(spfac); 800 sp.doPutToMap(p.getMap()); 801 table.update(e, f, sp); 802 } 803 } 804 } 805 if (debug) { 806 logger.info("table = " + table); 807 } 808 return; 809 } 810 811 812 /** 813 * Parsing method for polynomial ring. Syntax: 814 * 815 * <pre> 816 * coeffRing varList termOrderName polyList 817 * </pre> 818 * 819 * @return the next polynomial ring. 820 * @throws IOException 821 */ 822 @SuppressWarnings("unchecked") 823 public GenPolynomialRing nextPolynomialRing() throws IOException { 824 //String comments = ""; 825 //comments += nextComment(); 826 //if (debug) logger.debug("comment = " + comments); 827 828 RingFactory coeff = nextCoefficientRing(); 829 logger.info("coeff = " + coeff); 830 831 vars = nextVariableList(); 832 logger.info("vars = " + Arrays.toString(vars)); 833 if (vars != null) { 834 nvars = vars.length; 835 } 836 837 tord = nextTermOrder(); 838 logger.info("tord = " + tord); 839 // check more TOs 840 841 initFactory(coeff, parsedCoeff); // global: nvars, tord, vars 842 // now pfac is initialized 843 return pfac; 844 } 845 846 847 /** 848 * Parsing method for solvable polynomial ring. Syntax: 849 * 850 * <pre> 851 * varList termOrderName relationTable polyList 852 * </pre> 853 * 854 * @return the next solvable polynomial ring. 855 * @throws IOException 856 */ 857 @SuppressWarnings("unchecked") 858 public GenSolvablePolynomialRing nextSolvablePolynomialRing() throws IOException { 859 //String comments = ""; 860 //comments += nextComment(); 861 //if (debug) logger.debug("comment = " + comments); 862 863 RingFactory coeff = nextCoefficientRing(); 864 logger.info("coeff = " + coeff.getClass().getSimpleName()); 865 866 vars = nextVariableList(); 867 logger.info("vars = " + Arrays.toString(vars)); 868 if (vars != null) { 869 nvars = vars.length; 870 } 871 872 tord = nextTermOrder(); 873 logger.info("tord = " + tord); 874 // check more TOs 875 876 initFactory(coeff, parsedCoeff); // must be because of symmetric read 877 initSolvableFactory(coeff, parsedCoeff); // global: nvars, tord, vars 878 //System.out.println("pfac = " + pfac); 879 //System.out.println("spfac = " + spfac); 880 881 nextRelationTable(); 882 if (logger.isInfoEnabled()) { 883 logger.info("table = " + table + ", tok = " + tok); 884 } 885 // now spfac is initialized 886 return spfac; 887 } 888 889 890 static boolean digit(char x) { 891 return '0' <= x && x <= '9'; 892 } 893 894 895 //static boolean letter(char x) { 896 // return ('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z'); 897 //} 898 899 900 // unused 901 public void nextComma() throws IOException { 902 int tt; 903 if (tok.ttype == ',') { 904 tt = tok.nextToken(); 905 if (debug) { 906 logger.debug("after comma: " + tt); 907 } 908 } 909 } 910 911 912 /** 913 * Parse variable list from String. 914 * @param s String. Syntax: 915 * 916 * <pre> 917 * (n1,...,nk) 918 * </pre> 919 * 920 * or 921 * 922 * <pre> 923 * (n1 ... nk) 924 * </pre> 925 * 926 * parenthesis are optional. 927 * @return array of variable names found in s. 928 */ 929 public static String[] variableList(String s) { 930 String[] vl = null; 931 if (s == null) { 932 return vl; 933 } 934 String st = s.trim(); 935 if (st.length() == 0) { 936 return new String[0]; 937 } 938 if (st.charAt(0) == '(') { 939 st = st.substring(1); 940 } 941 if (st.charAt(st.length() - 1) == ')') { 942 st = st.substring(0, st.length() - 1); 943 } 944 st = st.replaceAll(",", " "); 945 List<String> sl = new ArrayList<String>(); 946 Scanner sc = new Scanner(st); 947 while (sc.hasNext()) { 948 String sn = sc.next(); 949 sl.add(sn); 950 } 951 sc.close(); 952 vl = new String[sl.size()]; 953 int i = 0; 954 for (String si : sl) { 955 vl[i] = si; 956 i++; 957 } 958 return vl; 959 } 960 961}