001/* 002 * $Id: SGBFactory.java 5902 2018-08-22 21:25:06Z kredel $ 003 */ 004 005package edu.jas.gbufd; 006 007 008import org.apache.logging.log4j.Logger; 009import org.apache.logging.log4j.LogManager; 010 011import edu.jas.arith.BigInteger; 012import edu.jas.arith.BigRational; 013import edu.jas.arith.ModInteger; 014import edu.jas.arith.ModIntegerRing; 015import edu.jas.arith.ModLong; 016import edu.jas.arith.ModLongRing; 017import edu.jas.gb.OrderedMinPairlist; 018import edu.jas.gb.OrderedPairlist; 019import edu.jas.gb.OrderedSyzPairlist; 020import edu.jas.gb.PairList; 021import edu.jas.gb.SGBProxy; 022import edu.jas.gb.SolvableGroebnerBaseAbstract; 023import edu.jas.gb.SolvableGroebnerBaseParallel; 024import edu.jas.gb.SolvableGroebnerBaseSeq; 025import edu.jas.gb.SolvableReductionSeq; 026import edu.jas.kern.ComputerThreads; 027import edu.jas.poly.GenPolynomial; 028import edu.jas.poly.GenPolynomialRing; 029import edu.jas.structure.GcdRingElem; 030import edu.jas.structure.QuotPairFactory; 031import edu.jas.structure.RingFactory; 032import edu.jas.structure.ValueFactory; 033import edu.jas.ufd.Quotient; 034import edu.jas.ufd.QuotientRing; 035 036 037// import edu.jas.application.SolvableResidueRing; // package cycle 038 039 040/** 041 * Solvable Groebner bases algorithms factory. Select appropriate Solvable 042 * Groebner bases engine based on the coefficient types. 043 * @author Heinz Kredel 044 * @usage To create objects that implement the <code>SolvableGroebnerBase</code> 045 * interface use the <code>SGBFactory</code>. It will select an 046 * appropriate implementation based on the types of polynomial 047 * coefficients C. The method to obtain an implementation is 048 * <code>getImplementation()</code>. It returns an object of a class 049 * which implements the <code>SolvableGroebnerBase</code> interface, more 050 * precisely an object of abstract class 051 * <code>SolvableGroebnerBaseAbstract</code>. 052 * 053 * <pre> 054 * 055 * SolvableGroebnerBase<CT> engine; 056 * engine = SGBFactory.<CT> getImplementation(cofac); 057 * c = engine.GB(A); 058 * </pre> 059 * 060 * For example, if the coefficient type is BigInteger, the usage looks 061 * like 062 * 063 * <pre> 064 * 065 * BigInteger cofac = new BigInteger(); 066 * SolvableGroebnerBase<BigInteger> engine; 067 * engine = SGBFactory.getImplementation(cofac); 068 * c = engine.GB(A); 069 * </pre> 070 * 071 * @see edu.jas.gb.GroebnerBase 072 * @see edu.jas.gb.SolvableGroebnerBase 073 * @see edu.jas.application.GBAlgorithmBuilder 074 */ 075 076public class SGBFactory { 077 078 079 private static final Logger logger = LogManager.getLogger(SGBFactory.class); 080 081 082 private static final boolean debug = logger.isDebugEnabled(); 083 084 085 /** 086 * Protected factory constructor. 087 */ 088 protected SGBFactory() { 089 } 090 091 092 /** 093 * Determine suitable implementation of GB algorithms, no factory case. 094 * @return GB algorithm implementation for field coefficients. 095 */ 096 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<C> getImplementation() { 097 logger.warn("no coefficent factory given, assuming field coeffcients"); 098 SolvableGroebnerBaseAbstract<C> bba = new SolvableGroebnerBaseSeq<C>(); 099 return bba; 100 } 101 102 103 /** 104 * Determine suitable implementation of GB algorithms, case ModLong. 105 * @param fac ModLongRing. 106 * @return GB algorithm implementation. 107 */ 108 public static SolvableGroebnerBaseAbstract<ModLong> getImplementation(ModLongRing fac) { 109 return getImplementation(fac, new OrderedPairlist<ModLong>()); 110 } 111 112 113 /** 114 * Determine suitable implementation of GB algorithms, case ModLong. 115 * @param fac ModLongRing. 116 * @param pl pair selection strategy 117 * @return GB algorithm implementation. 118 */ 119 public static SolvableGroebnerBaseAbstract<ModLong> getImplementation(ModLongRing fac, 120 PairList<ModLong> pl) { 121 SolvableGroebnerBaseAbstract<ModLong> bba; 122 if (fac.isField()) { 123 bba = new SolvableGroebnerBaseSeq<ModLong>(pl); 124 } else { 125 bba = new SolvableGroebnerBasePseudoSeq<ModLong>(fac, pl); 126 } 127 return bba; 128 } 129 130 131 /** 132 * Determine suitable implementation of GB algorithms, case ModInteger. 133 * @param fac ModIntegerRing. 134 * @return GB algorithm implementation. 135 */ 136 public static SolvableGroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac) { 137 return getImplementation(fac, new OrderedPairlist<ModInteger>()); 138 } 139 140 141 /** 142 * Determine suitable implementation of GB algorithms, case ModInteger. 143 * @param fac ModIntegerRing. 144 * @param pl pair selection strategy 145 * @return GB algorithm implementation. 146 */ 147 public static SolvableGroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac, 148 PairList<ModInteger> pl) { 149 SolvableGroebnerBaseAbstract<ModInteger> bba; 150 if (fac.isField()) { 151 bba = new SolvableGroebnerBaseSeq<ModInteger>(pl); 152 } else { 153 bba = new SolvableGroebnerBasePseudoSeq<ModInteger>(fac, pl); 154 } 155 return bba; 156 } 157 158 159 /** 160 * Determine suitable implementation of GB algorithms, case BigInteger. 161 * @param fac BigInteger. 162 * @return GB algorithm implementation. 163 */ 164 public static SolvableGroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac) { 165 return getImplementation(fac, GBFactory.Algo.igb); 166 } 167 168 169 /** 170 * Determine suitable implementation of GB algorithms, case BigInteger. 171 * @param fac BigInteger. 172 * @param a algorithm, a = igb, egb, dgb. 173 * @return GB algorithm implementation. 174 */ 175 public static SolvableGroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, GBFactory.Algo a) { 176 return getImplementation(fac, a, new OrderedPairlist<BigInteger>()); 177 } 178 179 180 /** 181 * Determine suitable implementation of GB algorithms, case BigInteger. 182 * @param fac BigInteger. 183 * @param pl pair selection strategy 184 * @return GB algorithm implementation. 185 */ 186 public static SolvableGroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, 187 PairList<BigInteger> pl) { 188 return getImplementation(fac, GBFactory.Algo.igb, pl); 189 } 190 191 192 /** 193 * Determine suitable implementation of GB algorithms, case BigInteger. 194 * @param fac BigInteger. 195 * @param a algorithm, a = igb, egb, dgb. 196 * @param pl pair selection strategy 197 * @return GB algorithm implementation. 198 */ 199 public static SolvableGroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, 200 GBFactory.Algo a, PairList<BigInteger> pl) { 201 SolvableGroebnerBaseAbstract<BigInteger> bba; 202 switch (a) { 203 case igb: 204 bba = new SolvableGroebnerBasePseudoSeq<BigInteger>(fac, pl); 205 break; 206 case egb: 207 throw new UnsupportedOperationException("egb algorithm not available for BigInteger " + a); 208 case dgb: 209 throw new UnsupportedOperationException("dgb algorithm not available for BigInteger " + a); 210 default: 211 throw new IllegalArgumentException("algorithm not available for BigInteger " + a); 212 } 213 return bba; 214 } 215 216 217 /** 218 * Determine suitable implementation of GB algorithms, case BigRational. 219 * @param fac BigRational. 220 * @return GB algorithm implementation. 221 */ 222 public static SolvableGroebnerBaseAbstract<BigRational> getImplementation(BigRational fac) { 223 return getImplementation(fac, GBFactory.Algo.qgb); 224 } 225 226 227 /** 228 * Determine suitable implementation of GB algorithms, case BigRational. 229 * @param fac BigRational. 230 * @param a algorithm, a = qgb, ffgb. 231 * @return GB algorithm implementation. 232 */ 233 public static SolvableGroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, 234 GBFactory.Algo a) { 235 return getImplementation(fac, a, new OrderedPairlist<BigRational>()); 236 } 237 238 239 /** 240 * Determine suitable implementation of GB algorithms, case BigRational. 241 * @param fac BigRational. 242 * @param pl pair selection strategy 243 * @return GB algorithm implementation. 244 */ 245 public static SolvableGroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, 246 PairList<BigRational> pl) { 247 return getImplementation(fac, GBFactory.Algo.qgb, pl); 248 } 249 250 251 /** 252 * Determine suitable implementation of GB algorithms, case BigRational. 253 * @param fac BigRational. 254 * @param a algorithm, a = qgb, ffgb. 255 * @param pl pair selection strategy 256 * @return GB algorithm implementation. 257 */ 258 public static SolvableGroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, 259 GBFactory.Algo a, PairList<BigRational> pl) { 260 SolvableGroebnerBaseAbstract<BigRational> bba; 261 switch (a) { 262 case qgb: 263 bba = new SolvableGroebnerBaseSeq<BigRational>(pl); 264 break; 265 case ffgb: 266 throw new UnsupportedOperationException("ffgb algorithm not available for BigRational " + a); 267 //PairList<BigInteger> pli; 268 //if (pl instanceof OrderedMinPairlist) { 269 // pli = new OrderedMinPairlist<BigInteger>(); 270 //} else if (pl instanceof OrderedSyzPairlist) { 271 // pli = new OrderedSyzPairlist<BigInteger>(); 272 //} else { 273 // pli = new OrderedPairlist<BigInteger>(); 274 //} 275 //bba = new SolvableGroebnerBaseRational<BigRational>(pli); // pl not possible 276 //break; 277 default: 278 throw new IllegalArgumentException("algorithm not available for " + fac.toScriptFactory() 279 + ", Algo = " + a); 280 } 281 return bba; 282 } 283 284 285 /** 286 * Determine suitable implementation of GB algorithms, case Quotient 287 * coefficients. 288 * @param fac QuotientRing. 289 * @return GB algorithm implementation. 290 */ 291 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<Quotient<C>> getImplementation( 292 QuotientRing<C> fac) { 293 return getImplementation(fac, GBFactory.Algo.qgb); 294 } 295 296 297 /** 298 * Determine suitable implementation of GB algorithms, case Quotient 299 * coefficients. 300 * @param fac QuotientRing. 301 * @param a algorithm, a = qgb, ffgb. 302 * @return GB algorithm implementation. 303 */ 304 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<Quotient<C>> getImplementation( 305 QuotientRing<C> fac, GBFactory.Algo a) { 306 return getImplementation(fac, a, new OrderedPairlist<Quotient<C>>()); 307 } 308 309 310 /** 311 * Determine suitable implementation of GB algorithms, case Quotient 312 * coefficients. 313 * @param fac QuotientRing. 314 * @param pl pair selection strategy 315 * @return GB algorithm implementation. 316 */ 317 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<Quotient<C>> getImplementation( 318 QuotientRing<C> fac, PairList<Quotient<C>> pl) { 319 return getImplementation(fac, GBFactory.Algo.qgb, pl); 320 } 321 322 323 /** 324 * Determine suitable implementation of GB algorithms, case Quotient 325 * coefficients. 326 * @param fac QuotientRing. 327 * @param a algorithm, a = qgb, ffgb. 328 * @param pl pair selection strategy 329 * @return GB algorithm implementation. 330 */ 331 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<Quotient<C>> getImplementation( 332 QuotientRing<C> fac, GBFactory.Algo a, PairList<Quotient<C>> pl) { 333 SolvableGroebnerBaseAbstract<Quotient<C>> bba; 334 if (logger.isInfoEnabled()) { 335 logger.info("QuotientRing, fac = " + fac); 336 } 337 switch (a) { 338 case qgb: 339 bba = new SolvableGroebnerBaseSeq<Quotient<C>>(new SolvableReductionSeq<Quotient<C>>(), pl); 340 break; 341 case ffgb: 342 throw new UnsupportedOperationException("ffgb algorithm not available for " + a); 343 //PairList<GenPolynomial<C>> pli; 344 //if (pl instanceof OrderedMinPairlist) { 345 // pli = new OrderedMinPairlist<GenPolynomial<C>>(); 346 //} else if (pl instanceof OrderedSyzPairlist) { 347 // pli = new OrderedSyzPairlist<GenPolynomial<C>>(); 348 //} else { 349 // pli = new OrderedPairlist<GenPolynomial<C>>(); 350 //} 351 //bba = new SolvableGroebnerBaseQuotient<C>(fac, pli); // pl not possible 352 //break; 353 default: 354 throw new IllegalArgumentException("algorithm not available for Quotient " + a); 355 } 356 return bba; 357 } 358 359 360 /** 361 * Determine suitable implementation of GB algorithms, case (recursive) 362 * polynomial. 363 * @param fac GenPolynomialRing<C>. 364 * @return GB algorithm implementation. 365 */ 366 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 367 GenPolynomialRing<C> fac) { 368 return getImplementation(fac, GBFactory.Algo.igb); 369 } 370 371 372 /** 373 * Determine suitable implementation of GB algorithms, case (recursive) 374 * polynomial. 375 * @param fac GenPolynomialRing<C>. 376 * @param a algorithm, a = igb or egb, dgb if fac is univariate over a 377 * field. 378 * @return GB algorithm implementation. 379 */ 380 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 381 GenPolynomialRing<C> fac, GBFactory.Algo a) { 382 return getImplementation(fac, a, new OrderedPairlist<GenPolynomial<C>>()); 383 } 384 385 386 /** 387 * Determine suitable implementation of GB algorithms, case (recursive) 388 * polynomial. 389 * @param fac GenPolynomialRing<C>. 390 * @param pl pair selection strategy 391 * @return GB algorithm implementation. 392 */ 393 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 394 GenPolynomialRing<C> fac, PairList<GenPolynomial<C>> pl) { 395 return getImplementation(fac, GBFactory.Algo.igb, pl); 396 } 397 398 399 /** 400 * Determine suitable implementation of GB algorithms, case (recursive) 401 * polynomial. 402 * @param fac GenPolynomialRing<C>. 403 * @param a algorithm, a = igb or egb, dgb if fac is univariate over a 404 * field. 405 * @param pl pair selection strategy 406 * @return GB algorithm implementation. 407 */ 408 public static <C extends GcdRingElem<C>> SolvableGroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 409 GenPolynomialRing<C> fac, GBFactory.Algo a, PairList<GenPolynomial<C>> pl) { 410 SolvableGroebnerBaseAbstract<GenPolynomial<C>> bba; 411 switch (a) { 412 case igb: 413 bba = new SolvableGroebnerBasePseudoRecSeq<C>(fac, pl); 414 break; 415 case egb: 416 throw new UnsupportedOperationException("egb algorithm not available for " + a); 417 //if (fac.nvar > 1 || !fac.coFac.isField()) { 418 // throw new IllegalArgumentException("coefficients not univariate or not over a field" + fac); 419 //} 420 //bba = new ESolvableGroebnerBaseSeq<GenPolynomial<C>>(); // pl not suitable 421 //break; 422 case dgb: 423 throw new UnsupportedOperationException("dgb algorithm not available for " + a); 424 //if (fac.nvar > 1 || !fac.coFac.isField()) { 425 // throw new IllegalArgumentException("coefficients not univariate or not over a field" + fac); 426 //} 427 //bba = new DSolvableGroebnerBaseSeq<GenPolynomial<C>>(); // pl not suitable 428 //break; 429 default: 430 throw new IllegalArgumentException("algorithm not available for GenPolynomial<C> " + a); 431 } 432 return bba; 433 } 434 435 436 /* 437 * Determine suitable implementation of GB algorithms, case regular rings. 438 * @param fac RegularRing. 439 * @return GB algorithm implementation. 440 public static <C extends RingElem<C>> SolvableGroebnerBaseAbstract<Product<C>> getImplementation( 441 ProductRing<C> fac) { 442 SolvableGroebnerBaseAbstract<Product<C>> bba; 443 if (fac.onlyFields()) { 444 bba = new RSolvableGroebnerBaseSeq<Product<C>>(); 445 } else { 446 bba = new RSolvableGroebnerBasePseudoSeq<Product<C>>(fac); 447 } 448 return bba; 449 } 450 */ 451 452 453 /** 454 * Determine suitable implementation of GB algorithms, other cases. 455 * @param fac RingFactory<C>. 456 * @return GB algorithm implementation. 457 */ 458 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 459 SolvableGroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac) { 460 return getImplementation(fac, new OrderedPairlist<C>()); 461 } 462 463 464 /** 465 * Determine suitable implementation of GB algorithms, other cases. 466 * @param fac RingFactory<C>. 467 * @param pl pair selection strategy 468 * @return GB algorithm implementation. 469 */ 470 @SuppressWarnings({ "cast", "unchecked" }) 471 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 472 SolvableGroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac, PairList<C> pl) { 473 if (debug) { 474 logger.debug("fac = " + fac.getClass().getName()); // + ", fac = " + fac.toScript()); 475 } 476 if (fac.isField()) { 477 return new SolvableGroebnerBaseSeq<C>(pl); 478 } 479 if (fac instanceof ValueFactory) { 480 return new SolvableGroebnerBasePseudoSeq<C>(fac, pl); 481 } 482 if (fac instanceof QuotPairFactory) { 483 return new SolvableGroebnerBaseSeq<C>(pl); 484 } 485 SolvableGroebnerBaseAbstract bba = null; 486 Object ofac = fac; 487 if (ofac instanceof GenPolynomialRing) { 488 PairList<GenPolynomial<C>> pli; 489 if (pl instanceof OrderedMinPairlist) { 490 pli = new OrderedMinPairlist<GenPolynomial<C>>(); 491 } else if (pl instanceof OrderedSyzPairlist) { 492 pli = new OrderedSyzPairlist<GenPolynomial<C>>(); 493 } else { 494 pli = new OrderedPairlist<GenPolynomial<C>>(); 495 } 496 GenPolynomialRing<C> rofac = (GenPolynomialRing<C>) ofac; 497 SolvableGroebnerBaseAbstract<GenPolynomial<C>> bbr = new SolvableGroebnerBasePseudoRecSeq<C>( 498 rofac, pli); // not pl 499 bba = (SolvableGroebnerBaseAbstract) bbr; 500 //} else if (ofac instanceof ProductRing) { 501 // ProductRing pfac = (ProductRing) ofac; 502 // if (pfac.onlyFields()) { 503 // bba = new RSolvableGroebnerBaseSeq<Product<C>>(); 504 // } else { 505 // bba = new RSolvableGroebnerBasePseudoSeq<Product<C>>(pfac); 506 // } 507 } else { 508 bba = new SolvableGroebnerBasePseudoSeq<C>(fac, pl); 509 } 510 logger.info("bba = " + bba.getClass().getName()); 511 return bba; 512 } 513 514 515 /** 516 * Determine suitable parallel/concurrent implementation of GB algorithms if 517 * possible. 518 * @param fac RingFactory<C>. 519 * @return GB proxy algorithm implementation. 520 */ 521 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 522 SolvableGroebnerBaseAbstract<C> getProxy(RingFactory<C> fac) { 523 return getProxy(fac, new OrderedPairlist<C>()); 524 } 525 526 527 /** 528 * Determine suitable parallel/concurrent implementation of GB algorithms if 529 * possible. 530 * @param fac RingFactory<C>. 531 * @param pl pair selection strategy 532 * @return GB proxy algorithm implementation. 533 */ 534 @SuppressWarnings({ "unchecked" }) 535 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 536 SolvableGroebnerBaseAbstract<C> getProxy(RingFactory<C> fac, PairList<C> pl) { 537 if (ComputerThreads.NO_THREADS) { 538 return SGBFactory.<C> getImplementation(fac, pl); 539 } 540 if (debug) { 541 logger.debug("proxy fac = " + fac.getClass().getName()); 542 } 543 int th = (ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS - 1 : 2); 544 if (fac.isField()) { 545 SolvableGroebnerBaseAbstract<C> e1 = new SolvableGroebnerBaseSeq<C>(pl); 546 SolvableGroebnerBaseAbstract<C> e2 = new SolvableGroebnerBaseParallel<C>(th, pl); 547 return new SGBProxy<C>(e1, e2); 548 } else if (fac.characteristic().signum() == 0) { 549 if (fac instanceof GenPolynomialRing) { 550 GenPolynomialRing pfac = (GenPolynomialRing) fac; 551 OrderedPairlist ppl = new OrderedPairlist<GenPolynomial<C>>(); 552 SolvableGroebnerBaseAbstract e1 = new SolvableGroebnerBasePseudoRecSeq<C>(pfac, ppl); 553 logger.warn("no parallel version available, returning sequential version"); 554 return e1; 555 //SolvableGroebnerBaseAbstract e2 = new SolvableGroebnerBasePseudoRecParallel<C>(th, pfac, ppl); 556 //return new SGBProxy<C>(e1, e2); 557 } 558 SolvableGroebnerBaseAbstract<C> e1 = new SolvableGroebnerBasePseudoSeq<C>(fac, pl); 559 logger.warn("no parallel version available, returning sequential version"); 560 return e1; 561 //SolvableGroebnerBaseAbstract<C> e2 = new SolvableGroebnerBasePseudoParallel<C>(th, fac, pl); 562 //return new SGBProxy<C>(e1, e2); 563 } 564 return getImplementation(fac, pl); 565 } 566 567 568 /** 569 * Determine suitable parallel/concurrent implementation of GB algorithms if 570 * possible. 571 * @param fac RingFactory<C>. 572 * @return GB proxy algorithm implementation. 573 */ 574 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 575 SolvableGroebnerBaseAbstract<GenPolynomial<C>> getProxy(GenPolynomialRing<C> fac) { 576 if (ComputerThreads.NO_THREADS) { 577 //return SGBFactory.<GenPolynomial<C>> getImplementation(fac); 578 return SGBFactory.getImplementation(fac); 579 } 580 if (debug) { 581 logger.debug("fac = " + fac.getClass().getName()); 582 } 583 //int th = (ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS - 1 : 2); 584 OrderedPairlist<GenPolynomial<C>> ppl = new OrderedPairlist<GenPolynomial<C>>(); 585 SolvableGroebnerBaseAbstract<GenPolynomial<C>> e1 = new SolvableGroebnerBasePseudoRecSeq<C>(fac, ppl); 586 logger.warn("no parallel version available, returning sequential version"); 587 return e1; 588 //SolvableGroebnerBaseAbstract<GenPolynomial<C>> e2 = new SolvableGroebnerBasePseudoRecParallel<C>(th, fac, ppl); 589 //return new SGBProxy<GenPolynomial<C>>(e1, e2); 590 //return new SGBProxy(e1, e2); 591 } 592 593}