Changeset 7d6fbd in git
- Timestamp:
- Dec 21, 2021, 4:26:26 PM (2 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- 46f3d0d3afbd8ba07ae6c5d1c137e7cda665cee8
- Parents:
- 1edfd962c6e31ddded2bdf5875ec00ea82c7f349
- git-author:
- Hans Schoenemann <hannes@mathematik.uni-kl.de>2021-12-21 16:26:26+01:00
- git-committer:
- Hans Schoenemann <hannes@mathematik.uni-kl.de>2021-12-21 16:26:52+01:00
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/LIB/integralbasis.lib
r1edfd9 r7d6fbd 1 ////////////////////////////////////////////////////////////////////////////// 2 version="version integralbasis.lib 4.1.2.0 Feb_2019 "; // $Id$ 1 /////////////////////////////////////////////////////////////////////////////// 2 /////////////////////////////////////////////////////////////////////////////// 3 /////////////////////////////////////////////////////////////////////////////// 4 version="version integralbasis.lib 4.2.1.3 Dec_2021 "; // $Id$ 3 5 category="Commutative Algebra"; 4 6 info=" 5 7 LIBRARY: integralbasis.lib Integral basis in algebraic function fields 6 AUTHORS: J. Boehm, j.boehm at mx.uni-saarland.de @*7 W. Decker, decker at mathematik.uni-kl.de > @*8 S. Laplagne, slaplagn at dm.uba.ar @*9 F. Seelisch, seelischat mathematik.uni-kl.de8 AUTHORS: J. Boehm, boehm at mathematik.uni-kl.de 9 W. Decker, decker at mathematik.uni-kl.de 10 S. Laplagne, slaplagn at dm.uba.ar 11 G. Pfister, pfister at mathematik.uni-kl.de 10 12 11 13 OVERVIEW: … … 19 21 20 22 PROCEDURES: 21 integralBasis(f, intVar); Integral basis of an algebraic function field 23 integralBasis(f, intVar, list #); Integral basis of an algebraic function field 24 polyDK(int d, int k, list #); Polynomial with an ordinary multiple point at the origin 25 monic(poly f); Makes a polynomial monic 26 henselGlobal(poly f, poly g, poly h, int order); Splits a polynomial using Hensel lifting 22 27 "; 23 28 24 29 LIB "normal.lib"; 30 LIB "locnormal.lib"; 31 LIB "assprimeszerodim.lib"; 32 LIB "puiseuxexpansions.lib"; 33 LIB "classify.lib"; // For init_debug() and debug_log() procedures 34 25 35 26 36 /////////////////////////////////////////////////////////////////////////////// … … 33 43 must be monic as polynomial in the intVar-th variable.@* 34 44 Optional parameters in list choose (can be entered in any order):@* 35 Parameters for selecting the algorithm:@*36 - \"global\" -> computes the integral basis by computing the37 normalization of R/<f>, where R is the base ring.@*45 Strategy:@* 46 - \"global\" -> computes the integral basis by global algorithms. This 47 forces \"normal\" option. @* 38 48 - \"local\" -> computes the integral basis by computing the 39 normalization of R/<f> localized at each component of the singular 40 locus of R/<f>, and then putting everything together. 41 This is the default option.@* 42 Other parameters:@* 49 local contribution at each component of the singular 50 locus of R/<f>, and then putting everything together. (Default option.) 51 @*Algorithm:@* 52 - \"normal\" -> the integral bases are computed using the normalization 53 algorithm.@* 54 - \"hensel\" -> the integral bases are computed using a special 55 algorithm, based on Hensel lifting. (Default option.) 56 - \"modular\" -> uses modular algorithms for computing Groebner bases, 57 radicals and decompositions whenever possible. Can be used together 58 with any of the other options. The ground field must have 59 characteristic 0. (Default option for ground fields of characteristic 60 0.)@* 61 - \"nonModular\" -> do not uses modular algorithms. (Default option for 62 ground fields of positive charecteristic.)@* 63 - \"rotation\" -> apply a rotation when there are singularities 64 with the same X-coordinate @* 65 - \"noRotation\" -> does not apply a rotation when there are singularities 66 with the same X-coordinate (Default option.)@* 67 Other options:@* 68 - \"atOrigin\" -> will compute the local contribution at the origin 69 to the integral basis, assuming that the curve has a singularity at 70 the origin.@* 43 71 - \"isIrred\" -> assumes that the input polynomial f is irreducible, 44 72 and therefore will not check this. If this option is given but f is not 45 73 irreducible, the output might be wrong.@* 46 74 - list(\"inputJ\", ideal inputJ) -> takes as initial test ideal the 47 ideal inputJ. This option is only for use in other procedures. Using48 this option, the result might not be the integral basis.@*75 ideal inputJ. This option is only for use in other procedures. 76 Using this option, the result might not be the integral basis. 49 77 (When this option is given, the global option will be used.)@* 50 78 - list(\"inputC\", ideal inputC) -> takes as initial conductor the 51 79 ideal inputC. This option is only for use in other procedures. Using 52 this option, the result might not be the integral basis.@* 53 (When this option is given, the global option will be used.)@* 80 this option, the result might not be the integral basis. (When this 81 option is given, the global option will be used.)@* 82 - \"locBasis\" -> when computing the integral basis at a prime or 83 primary component, it computes a local basis, that is, a basis that is 84 integral only over the ring localized at the component. This option 85 is only valid when \"atOrigin\" is chosen or an initial test ideal or 86 conductor is given.@* 54 87 RETURN: a list, say l, of size 2. 55 88 l[1] is an ideal I and l[2] is a polynomial D such that the integral … … 61 94 element (indicated by intVar), f gives the integral equation and n is 62 95 the degree of f as a polynomial in y.@* 63 64 96 THEORY: We compute the integral basis of the integral closure of k[x] in k(x,y) 65 97 by computing the normalization of the affine ring k[x,y]/<f> and … … 71 103 { 72 104 int i; 73 ideal inputJ = 0; 74 ideal inputC = 0; 75 string algorithm = "local"; // The default option is "local" 76 int checkIrred = 1; 105 106 ideal inputJ = 0; // Initial test ideal (local approach) 107 ideal inputC = 0; // Initial conductor ideal (local approach) 108 109 string strategy = "local"; // The default strategy is "local" 110 string algorithm = "hensel"; // The default algorithm is "hensel" 111 string compType = ""; 112 ideal compo = 0; 113 114 115 // Modular algorithms 116 // The default is not using modular algorithms 117 int modular; 118 if(char(basering) > 0) 119 { 120 modular = 0; 121 } else 122 { 123 modular = 0; 124 } 125 126 int useRotation = 0; 127 128 int checkIrred = 1; // Checks if the input polynomial is irreducible 129 130 int locBasis = 0; // The default is to compute a non-local basis 131 132 int dbg = printlevel - voice + 2; 133 134 int check0 = 0; 135 //int check0 = 1; 77 136 78 137 //--------------------------- read the input options--------------------------- … … 82 141 { 83 142 if (#[i]=="local"){ 84 algorithm= "local";143 strategy = "local"; 85 144 } 86 145 if (#[i]=="global"){ 87 algorithm = "global"; 146 strategy = "global"; 147 } 148 if (#[i]=="modular"){ 149 modular = 1; 150 } 151 if (#[i]=="nonModular"){ 152 modular = 0; 153 } 154 if (#[i]=="rotation"){ 155 useRotation = 1; 156 } 157 if (#[i]=="noRotation"){ 158 useRotation = 0; 159 } 160 if (#[i]=="normal"){ 161 algorithm = "normal"; 162 } 163 if (#[i]=="hensel"){ 164 algorithm = "hensel"; 165 } 166 if (#[i]=="atOrigin"){ 167 compType = "inputJ"; 168 check0 = 0; // Do not check at the origin 169 compo = maxideal(1); 170 strategy = "atCompo"; // Computes only the local contribution at compo 171 } 172 if (#[i]=="check0"){ 173 check0 = 1; 174 } 175 if (#[i]=="noCheck0"){ 176 check0 = 0; 177 } 178 if (#[i]=="locBasis"){ 179 locBasis = 1; 88 180 } 89 181 if (#[i]=="isIrred"){ … … 91 183 } 92 184 } 93 if(typeof(#[i]) == "list"){ 94 if(size(#[i]) == 2){ 95 if (#[i][1]=="inputJ"){ 96 if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")){ 97 inputJ = #[i][2]; 98 algorithm = "global"; 185 186 if(typeof(#[i]) == "list") 187 { 188 if(size(#[i]) == 2) 189 { 190 if (#[i][1]=="inputJ") 191 { 192 if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")) 193 { 194 if(!isZeroIdeal(#[i][2])) 195 { 196 // Computes only the local contribution at inputJ 197 compType = "inputJ"; 198 compo = #[i][2]; 199 strategy = "atCompo"; 200 dbprint(dbg, "// Ideal J read from the input parameters."); 201 } 99 202 } 100 203 } 101 204 } 102 if (#[i][1]=="inputC"){ 103 if(size(#[i]) == 2){ 104 if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")){ 105 inputC = #[i][2]; 106 algorithm = "global"; 205 if (#[i][1]=="inputC") 206 { 207 if(size(#[i]) == 2) 208 { 209 if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")) 210 { 211 if(!isZeroIdeal(#[i][2])) 212 { 213 // Computes only the local contribution at inputC 214 strategy = "atCompo"; 215 if(algorithm != "normal") 216 { 217 compType = "inputJ"; 218 compo = radical(#[i][2]); 219 dbprint(dbg, "Ideal J read from the input parameters. (The radical of the conductor is used.)"); 220 } else 221 { 222 compType = "inputC"; 223 compo = #[i][2]; 224 dbprint(dbg, "Ideal C read from the input parameters."); 225 } 226 } 107 227 } 108 228 } … … 136 256 137 257 // The polynomial f must be irreducible. 138 if(checkIrred == 1){ 139 if(factorize(f)[2] != [1,1]){ 258 if(checkIrred == 1) 259 { 260 if(factorize(f)[2] != [1,1]) 261 { 140 262 ERROR("The input polynomial must be irreducible."); 141 263 } 142 264 } 143 265 266 // If the integral variable is the first one, we change the order of the 267 // variables. 268 if(intVar == 1) 269 { 270 def R = basering; 271 list rl = ringlist(R); 272 def temp = rl[2][1]; 273 rl[2][1] = rl[2][2]; 274 rl[2][2] = temp; 275 def S = ring(rl); 276 setring S; 277 poly f = imap(R, f); 278 ideal compo = imap(R, compo); 279 } 280 281 282 // We chech if the only singularity is at the origin. 283 //check0 = 0; 284 if(check0 == 1) 285 { 286 "Check at origin"; 287 int c0 = checkAt0(f, modular); 288 289 if(c0 == 1) 290 { 291 compType = "inputJ"; 292 compo = maxideal(1); 293 strategy = "atCompo"; // Computes only the local contribution at compo 294 } else { 295 } 296 } 297 144 298 //--------------------- computing the integral basis -------------------------- 145 return(cancelCF(integralBasisMain(f, algorithm, inputJ, inputC, intVar))); 299 dbprint(dbg, "Computing the integral basis..."); 300 list ib = integralBasisMain(f, strategy, algorithm, modular, compType, compo, locBasis, useRotation); 301 302 ideal num = ib[1]; 303 poly den = ib[2]; 304 dbprint(dbg, "Integral basis computation finished."); 305 //--------------------- computation finished ---------------------------------- 306 307 // We reverse the change in the order of the variables. 308 if(intVar == 1) 309 { 310 setring R; 311 ideal num = imap(S, num); 312 poly den = imap(S, den); 313 list ib = num, den; 314 } 315 return(cancelCF(ib)); 146 316 } 147 317 example … … 161 331 /////////////////////////////////////////////////////////////////////////////// 162 332 163 static proc integralBasisMain(poly f, string algorithm, ideal inputJ, ideal inputC, int intVar) 164 // Computes the integral basis of R/<f>, from the normalizaiton of R/<f>. 165 // inputC is the conductor ideal to be used in proc normal. 166 // If inputC = < 0 >, then the default conductor ideal is used (the full 167 // jacobian ideal). 168 // inputJ is the test ideal to be used in proc normal. 169 // If inputJ = < 0 >, then the default test ideal is used (the radical of the 170 // conductor). 171 { 172 int dbg = printlevel - voice + 2; 333 static proc integralBasisMain(poly f, string strategy, string algorithm, int modular, string compType, ideal compo, int locBasis, int useRotation) 334 // Computes the integral basis of R/<f>. 335 // The integral variable is always the second variable. 336 { 337 338 int dbg = printlevel - voice + 3; 173 339 int i, j; 174 int newRing = 0; // If = 1, a new ring with dp ordering was used. 340 341 int norToInt = 1; // Indicates if a conversion from normalization to 342 // integral basis is needed. 343 344 int newRing = 0; // If newRing = 1, a new ring with dp ordering was used. 345 list ib; 175 346 def origR = basering; 347 ideal normalGen; 348 poly D; 176 349 177 350 //--------------------- moving to a ring with dp ordering --------------------- 178 if(ordstr(origR) != "dp(2),C"){ 351 string s = ordstr(origR); 352 if(s[1,2] != "dp") 353 { 179 354 // We change to dp ordering. 180 355 list rl = ringlist(origR); 181 356 list origOrd = rl[3]; 182 list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0); 357 int jj = attrib(origR,"maxExp"); 358 359 list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0), list("L", jj); 183 360 rl[3] = newOrd; 184 361 def R = ring(rl); 185 362 setring R; 186 363 poly f = fetch(origR, f); 187 ideal inputJ = fetch(origR, inputJ); 188 ideal inputC = fetch(origR, inputC); 364 ideal compo = fetch(origR, compo); 365 ideal normalGen; 366 poly D; 189 367 newRing = 1; 190 } else { 368 } else 369 { 191 370 def R = basering; 192 371 } … … 194 373 //-------------------------------- basic data --------------------------------- 195 374 // The degree of f with respect to the variable intVar 196 ideal I = f; 197 int n = size(coeffs(f, var(intVar))) - 1; 375 int n = size(coeffs(f, var(2))) - 1; 198 376 199 377 // If the integral variable is the first, then the universal denominator 200 378 // must be a polynomial in the second variable (and viceversa). 201 string conduStr; 202 if(intVar == 1){ 203 conduStr = "var2"; 204 } else { 205 conduStr = "var1"; 206 } 379 // In this proc, the integral variables is always the second one. 380 string conduStr = "var1"; 207 381 list opts = conduStr; 208 382 209 //-------------------------- computes the normalization ----------------------- 210 if(algorithm == "local"){ 211 list nor = integralLocal(I, opts); 212 } else { 213 if(inputJ != 0){ 214 opts = insert(opts, list("inputJ", inputJ)); 215 } 216 if(inputC != 0){ 217 opts = insert(opts, list("inputC", inputC)); 218 } 219 list nor = normal(I, opts); 220 } 221 ideal normalGen = nor[2][1]; 222 poly D = normalGen[size(normalGen)]; // The universal denominator 383 //------------------------- computes the integral basis ----------------------- 384 ideal I = f; 385 int needRed = 1; 386 if(strategy == "atCompo") 387 { 388 norToInt = 0; 389 if(algorithm == "normal") 390 { 391 // Computes the integral basis at the component via normalization 392 opts = insert(opts, list(compType, compo)); 393 if(locBasis == 1) 394 { 395 "Warning: local basis are not implemented for the normalization algorithm. The output will be a global basis. 396 Use Hensel algorithm instead for computing local basis."; 397 } 398 ib = normal(I, opts)[2]; 399 if(size(ib) > 1){ 400 ERROR("The input polynomial is not irreducible."); 401 } 402 normalGen = ib[1]; 403 D = normalGen[size(normalGen)]; 404 } else 405 { 406 // Computes the integral basis at the component via puiseux expansions 407 ib = ibLocal(f, compo, locBasis, useRotation); 408 normalGen = ib[1]; 409 D = ib[2]; 410 } 411 } else 412 { 413 if(strategy == "local") 414 { 415 // Computes the integral basis my glueing together the local 416 // contrubutions 417 //"_DEBUG_ integralLocal"; 418 ib = integralLocal(I, modular, algorithm, useRotation, opts); 419 normalGen = ib[1]; 420 D = ib[2]; // The universal denominator 421 norToInt = ib[3]; 422 needRed = ib[4]; 423 } else 424 { 425 // Computes the global integral basis from the global normalization 426 // This can be changed to locNormal if "var1" is implemented in locNormal 427 ib = normal(I, opts)[2]; 428 normalGen = ib[1]; 429 D = normalGen[size(normalGen)]; 430 } 431 } 223 432 224 433 //Debug information 225 if(dbg >= 2){ 226 "The universal denominator is: ", D; 434 if(dbg >= 10) 435 { 436 "--Generators of the normalization."; 437 "----Numerator:"; normalGen; 438 "----Denominator: ", D; 227 439 } 228 440 229 441 //--------------- computes the integral basis from the normalization ---------- 442 443 int ttt = timer; 444 445 // Merging the components 446 debug_log_intbas(5, "norToInt: ", norToInt); 447 if(norToInt == 1) 448 { 449 // We define a new ring where the integral variable is the first (needed for 450 // reduction) and has the appropiate ordering. 451 dbprint(dbg, "--Computing the integral basis from the normalization..."); 452 int needGroeb = 0; // When all the components are already integral basis, no full groebner basis is needed. 453 454 list outp = normToInt(f, normalGen, D, needGroeb); 455 } else 456 { 457 list outp = normalGen, normalGen[1]; 458 } 459 debug_log_intbas(2, "----Time for merging: ", timer-ttt); 460 461 // Back to the original ring if needed 462 463 if(newRing == 1) 464 { 465 setring origR; 466 list outp; 467 outp[1] = fetch(R, normalGen); 468 outp[2] = outp[1][1]; 469 } 470 return(outp); 471 } 472 473 /////////////////////////////////////////////////////////////////////////////// 474 475 // Computes the integral basis by localizing at the different components of 476 // the singular locus. 477 // The main procedure for the computation of the local approach is ibLocal 478 479 static proc integralLocal(ideal I, int modular, string algorithm, int useRotation, list #) 480 { 481 int i, ii; 482 int dbg = printlevel - voice + 4; 483 int locBasis = 0; // This is a global procedure. 484 def R = basering; 485 486 poly f = I[1]; 487 488 list norOut; // Output of proc normal 489 ideal norT; // Temporary data. 490 ideal norT0; 491 poly denomT; // Temporary data. 492 poly condu; 493 poly conduT; // Temporary data 494 495 ideal nor; // Output of normal with the denominator changed to the 496 // common denominator. 497 ideal res; // The full integral basis 498 499 int good; 500 501 //--------------------------- read the input options--------------------------- 502 int denomOption = 0; 503 for ( i=1; i <= size(#); i++ ) 504 { 505 if ( typeof(#[i]) == "string" ) 506 { 507 if (#[i]=="var1") 508 {denomOption = 1;} 509 if (#[i]=="var2") 510 {denomOption = 2;} 511 } 512 } 513 514 //------------------------ singular locus computation ------------------------- 515 ideal J = f, diff(f, var(1)), diff(f, var(2)); 516 517 if(dbg >= 4){ 518 "The original singular locus is"; 519 J; 520 } 521 522 if(isOneIdeal(J)) 523 { 524 list out = trivialBasis(f); 525 "out"; 526 out; 527 return(list(out[1], out[2], 0, 0)); 528 } 529 530 //------------------- components of the singular locus------------------------ 531 int t = timer; 532 //if(algorithm == "normal") 533 //{ 534 // dbprint(dbg, "--Computing the primary decomposition of the singular locus..."); 535 // list pd = primdecGTZ(J); 536 //} else { 537 dbprint(dbg, "--Computing the associated primes of the singular locus..."); 538 if(modular == 1) 539 { 540 dbprint(dbg, " (Using modular algorithm.)"); 541 list pd = assPrimes(J); 542 } else 543 { 544 dbprint(dbg, " (Using non-modular algorithm.)"); 545 list pd = minAssGTZ(J); 546 } 547 //} 548 //"Time assoc primes: ", timer - t; 549 debug_log_intbas(2, "----Decomposition time:", timer - t); 550 551 dbprint(dbg-2, "----The number of components of the Singular Locus is ", size(pd)); 552 dbprint(dbg-4, "--Components of the Singular Locus:", pd); 553 554 555 // The following commented lines are not needed for integral basis, since 556 // all components are maximal. 557 // Computes the maximal components and the components included in them 558 //list comps = maxComps(pd); 559 // For each maximal component, it intersects all the components included in it 560 //list locs = intersectList(comps); 561 562 //------------------- normalization of each component-------------------------- 563 ideal compo; 564 poly cofactD, cofactC; 565 string compType; 566 dbprint(dbg, "--Computing the integral basis at each component..."); 567 for(i = 1; i <= size(pd); i++){ 568 if(debug_lvl() >= 2){ 569 t = timer; 570 } 571 if(dbg >= 2){ 572 t = timer; 573 } 574 good = 0; 575 // If algorithm == "new", we try to use the new algorithm. 576 //if((algorithm == "hensel") or (algorithm == "hoeij")) 577 //{ 578 // We localize at the prime components. 579 compType = "inputJ"; 580 compo = pd[i]; 581 //} else 582 //{ 583 // We use the primary components given by primdecGTZ as conductor in the 584 // normalization. 585 // We need to have the denominator in the transcendental variable. This 586 // is indicated in #. 587 // compType = "inputC"; 588 // compo = pd[i][1]; 589 //} 590 dbprint(dbg, "----Computing the integral basis of component ", i); 591 dbprint(dbg, "----Component: "); 592 if(dbg>=1){compo;} 593 594 norOut = intBasisComp(f, compType, compo, algorithm, locBasis, useRotation, #); 595 norT = norOut[1]; 596 denomT = norOut[2]; 597 // If the denominator is not a polynomial in x we change it. 598 if(deg(denomT, intvec(0,1)) > 0) 599 { 600 ideal PLex = yInTermOfx(compo); 601 poly px = PLex[1]; 602 poly newCondu = xCondu(px, norOut, I); 603 //"Old conductor: ", denomT; 604 //"New conductor: ", newCondu; 605 ideal norOutF = changeDenominatorFast(norOut[1], norOut[2], newCondu, I); 606 norOut[1] = norOutF; 607 norOut[2] = newCondu; 608 609 norT = norOut[1]; 610 denomT = norOut[2]; 611 } 612 if(size(pd)>1) 613 { 614 // We can remove redudant elements considering the generators as an ideal 615 // because the powers of Y will be added again later for merging 616 // the bases for the different components. 617 for(ii = 2; ii <= ncols(norT); ii++) 618 { 619 norT[ii] = reduce(norT[ii], groebner(denomT)); 620 } 621 //norT = groebner(norT); 622 norT = norT + 0; // Eliminate 0's in the ideal 623 } 624 //dbprint(dbg - 3, "------Normalization of component ", i, " output: ", norOut[1]); 625 dbprint(dbg - 3, "------Normalization of component ", i, " output: ", norT); 626 dbprint(dbg - 3, "------Denominator: ", denomT); 627 628 debug_log_intbas(2, "----Normalization of component ", i, " time: ", timer - t); 629 630 631 // We add up the normalizations at each localization, to construct the 632 // normalization of the whole ideal. 633 634 // We change the denominator of the normalization of the localized ring, 635 // to have the same denominator for all the normalizations. 636 //"The denominator is ", denomT; 637 //"The denominator is changed to ", condu; 638 639 // We compute the denominator as the lcm of the denominators. 640 conduT = condu; 641 if(condu != 0) 642 { 643 condu = lcm(condu, denomT); 644 cofactD = condu / denomT; 645 cofactC = condu / conduT; 646 647 if(dbg >= 2) 648 { 649 "----Changing the denominator..."; 650 if(dbg >= 4) 651 { 652 " from ", denomT, " to ", condu; 653 } 654 } 655 nor = norT * cofactD; 656 res = res * cofactC; 657 // We can also use changeDenominator, but it is slower. 658 // nor = changeDenominator(norT, denomT, condu, I); 659 // res = changeDenominator(res, conduT, condu, I); 660 } else 661 { 662 condu = denomT; 663 nor = norT; 664 } 665 666 // We sum the result to the previous results. 667 if(size(res)>0) 668 { 669 res = res, nor; 670 } else 671 { 672 res = nor; 673 } 674 } 675 676 // needRed indicates if reduction is needed to compute the full integral basis. 677 // When the local basis are already local integral basis, no reduction is needed. 678 int needRed; 679 if(algorithm == "normal") 680 { 681 needRed = 1; 682 } else 683 { 684 needRed = 0; 685 } 686 687 if((size(pd) == 1) and (algorithm != "normal")) 688 { 689 // Only one prime component in the singular locus, no need to 690 // merge the compontens together. 691 int norToInt = 0; 692 ideal num = norT; 693 poly den = denomT; 694 } else 695 { 696 dbprint(dbg, "--Putting all the components together..."); 697 ideal num = res; 698 poly den = condu; 699 int norToInt = 1; 700 } 701 // The output follows the output of proc normal, but we don't return the 702 // ring structure, only the generators. (We return 0 instead of the ring.) 703 704 return(list(num, den, norToInt, needRed)); 705 } 706 707 /////////////////////////////////////////////////////////////////////////////// 708 709 // Integral basis localized at a component. 710 static proc intBasisComp(poly f, string compType, ideal compo, string algorithm, int locBasis, int useRotation, list #) 711 { 712 int dbg = printlevel - voice + 4; 713 int good = 0; 714 list nor; 715 ideal norT; 716 poly denomT; 717 718 // If algorithm == "hensel", we use the new algorithm. 719 if(algorithm == "hensel"){ 720 nor = ibLocal(f, compo, locBasis, useRotation); 721 if(size(nor) != 0){ 722 norT = nor[1]; 723 denomT = nor[2]; 724 good = 1; 725 } else { 726 dbprint(dbg, "Using the normalization algorithm."); 727 } 728 } 729 // If not, or if the new algorithm did not succeed, we use normal. 730 if(good == 0){ 731 // # indicate which is the transcendental variable. 732 list opts = insert(#, list(compType, compo)); 733 ideal I = f; 734 nor = normal(I, opts)[2]; 735 if(size(nor) > 1){ 736 ERROR("The input polynomial is not irreducible."); 737 } 738 norT = nor[1]; 739 denomT = norT[size(norT)]; 740 } 741 return(list(norT, denomT)); 742 } 743 744 ////////////////////////////////////////////////////////////////////// 745 746 // Converts generators for the normalization into integral basis shape 747 // The third parameter indicates the variable for the integral basis 748 // It computes an element in the conductor in that variable. 749 static proc normToIntJacob(ideal U, poly den, poly v, poly f) 750 { 751 ideal jac = jacob(f); 752 ideal elimJ = elim(jac, v); 753 poly dJ = elimJ[1]; 754 option("redSB"); 755 756 ideal PP = changeDenominatorFast(U, den, dJ, f); 757 list l = normToInt(f, PP, dJ, 1); 758 return(l); 759 } 760 761 /////////////////////////////////////////////////////////////////////////////// 762 763 static proc cancelCF(list IB) 764 "USAGE: cancelCF(IB); IB list of type returned by integralBasis 765 RETURN: list of same type with common factor cancelled. 766 KEYWORDS: greatest common divisor. 767 " 768 { 769 int l = size(IB[1]); 770 poly GrCoDi = IB[2]; 771 int k = l; 772 while((GrCoDi != 1) && (k >=1)) 773 { 774 GrCoDi = gcd(GrCoDi,IB[1][k]); 775 k = k-1; 776 } 777 if(GrCoDi != 1) 778 { 779 for(k = 1; k <= l; k++) 780 { 781 IB[1][k] = IB[1][k]/GrCoDi; 782 } 783 IB[2] = IB[2]/GrCoDi; 784 } 785 return(IB); 786 } 787 788 /////////////////////////////////////////////////////////////////////////////// 789 790 // Converts generators for the normalization into integral basis shape 791 static proc normToInt(poly f, ideal normalGen, poly D, int needGroeb) 792 { 793 int dbg = printlevel - voice + 4; 794 option("redSB"); 795 f = reduce(f, groebner(D)); 796 797 dbprint(dbg, "--Computing the integral basis from the normalization..."); 798 int needRed = 1; 799 int i, j; 800 intvec vy = (0, 1); 801 int n = deg(f, vy); 802 int t; 803 230 804 // We define a new ring where the integral variable is the first (needed for 231 // reduction) and has the appropriate ordering. 805 // reduction) and has the appropiate ordering. 806 def R = basering; 232 807 list rl = ringlist(R); 233 rl[2] = list(var( intVar), var(3-intVar));808 rl[2] = list(var(2), var(1)); 234 809 rl[3] = list(list("C", 0), list("lp", intvec(1,1))); 235 810 def S = ring(rl); 236 811 setring S; 812 intvec vyS = (1, 0); 237 813 238 814 // We map the elements in the previous ring to the new one 239 815 poly f = imap(R, f); 816 poly D = imap(R, D); 817 240 818 ideal normalGen = imap(R, normalGen); 819 820 //needGroeb = 1; 821 822 if(needGroeb == 1) 823 { 824 t = timer; 825 ideal ID2 = normalGen, f, D; 826 normalGen= groebner(ID2); 827 debug_log_intbas(3, "----Time for groebner base of generators: ", timer - t); 828 } 829 830 t = timer; 241 831 242 832 // We create the system of generatos y^i*f_j. 243 833 list l; 244 ideal red = groebner(f); 245 for(j = 1; j <= size(normalGen); j++){ 246 l[j] = reduce(normalGen[j], red); 247 } 248 for(i = 1; i <= n-1; i++){ 249 for(j = 1; j <= size(normalGen); j++){ 250 l[size(l)+1] = reduce(var(1)^i*normalGen[j], red); 251 } 252 } 834 poly p; 835 836 if(needRed == 1) 837 { 838 dbprint(dbg - 1, "----Reduction..."); 839 ideal red = groebner(f); 840 poly pRed; 841 for(j = 1; j <= ncols(normalGen); j++) 842 { 843 l[j] = reduce(normalGen[j], red); 844 // REDUCTION NEEDED? 845 if(size(D) == 1) 846 { 847 pRed = reduce(l[j], groebner(D)); 848 if(deg(l[j], vyS) == deg(pRed, vyS)) 849 { 850 l[j] = pRed; 851 } 852 } 853 } 854 int sl = size(l); 855 poly pc; 856 857 for(j = 1; j <= sl; j++) 858 { 859 p = l[j]; 860 if(p != 0) 861 { 862 for(i = 1; i < n-deg(l[j], vyS); i++) 863 { 864 p = p * var(1); 865 866 // REDUCTION NEEDED? 867 if(size(D) == 1) 868 { 869 pRed = reduce(p, groebner(D)); 870 if(deg(p, vyS) == deg(pRed, vyS)) 871 { 872 p = pRed; 873 } 874 875 } 876 l[size(l)+1] = p; 877 } 878 } 879 } 880 } else 881 { 882 dbprint(dbg - 1, "----No reduction needed."); 883 ideal red = groebner(f); 884 for(j = 1; j <= ncols(normalGen); j++) 885 { 886 l[j] = reduce(normalGen[j], red); 887 } 888 } 889 890 debug_log_intbas(2, "------Time for reduction: ", timer - t); 253 891 254 892 // To eliminate the redundant elements, we look at the polynomials as … … 260 898 matrix coeffi[n + 1][2]; 261 899 262 for(i = 1; i<= size(l); i++){ 900 for(i = 1; i<= size(l); i++) 901 { 263 902 coeffi = coeffs(l[i], var(1)); 264 903 vecs[1..nrows(coeffi), i] = coeffi[1..nrows(coeffi), 1]; 265 904 } 266 905 module M = vecs; 906 dbprint(dbg - 1, "----Triangulating..."); 907 908 int tt = timer; 267 909 M = std(M); 268 910 911 debug_log_intbas(2, "------Time for std(M): ", timer - tt); 912 269 913 // We go back to the original ring. 270 setring origR;914 setring R; 271 915 module M = imap(S, M); 272 if(newRing == 1){ 273 poly D = fetch(R, D); 274 } 275 916 917 tt = timer; 276 918 // We go back from the module to the ring in two variables 277 ideal G; 278 poly g; 279 for(i = 1; i <= size(M); i++){ 280 g = 0; 281 for(j = 0; j <= n; j++){ 282 g = g + M[i][j+1] * var(intVar)^j; 283 } 284 G[i] = g; 285 } 919 matrix YY[1][n+1]; 920 for(j = 0; j <= n; j++) 921 { 922 YY[1, j+1] = var(2)^j; 923 } 924 ideal G = YY * M; 925 926 tt = timer; 927 // Clear common x factor 928 poly ggcd = D; 929 for(i = 1; i <= size(M); i++) 930 { 931 ggcd = gcd(ggcd, G[i]); 932 } 933 G = G / ggcd; 934 D = D / ggcd; 286 935 287 936 // The first element in the output is the ideal of numerators. … … 289 938 list outp = G, D; 290 939 940 debug_log_intbas(2, "------Time for triangulation: ", timer - tt); 941 291 942 return(outp); 292 943 } 293 944 945 946 /////////////////////////////////////////////////////////////////////// 947 // 948 // The new algorithm 949 // 950 /////////////////////////////////////////////////////////////////////// 951 952 // Computes the integral basis of R[y]/f, with R = k[x] localized at 953 // the x coordinates of the points in P. 954 // It uses the algorithm by Boehm, Decker, Laplagne, Pfister. 955 // If locBasis = 1, it doesnt take into account the the unit from f 956 // after localization 957 958 static proc ibLocal(poly f, ideal P, int locBasis, int useRotation){ 959 int dbg = printlevel - voice + 2; 960 P = groebner(P); 961 if(dbg - 1 > 0) 962 { 963 "Computing the integral basis at P = "; P; 964 } 965 966 int i,j; 967 int li; 968 int moved; 969 poly fT; 970 def R = basering; 971 poly x = var(1); 972 poly y = var(2); 973 intvec vy = (0,1); 974 intvec vx = (1,0); 975 976 ideal PLex = yInTermOfx(P); 977 poly px = PLex[1]; 978 poly py = PLex[size(PLex)]; 979 py = monic(py); 980 981 // This special case implements the Remark on the paper 982 // on an alternative approach without coordinate change 983 984 useRotation = 0; 985 //"useRotation: ", useRotation; 986 987 if(useRotation == 0) 988 { 989 // Case: rational x-coordinate and non-rational y-coordinate. 990 // We treat this as a special case, so that no coordinate change is used. 991 if((deg(py, vy) > 1) and (deg(px) <= 1)) 992 { 993 dbprint(dbg, "Case: non-rational y-coordinate."); 994 995 // We move the singularities to x = 0. 996 fT = moveToVar(f, px, x); 997 998 // We compute the integral basis. 999 list ib = ibNonRatY(fT, py, locBasis); 1000 1001 //"ib: ", ib; 1002 1003 // If the integral basis was not computed, we return an empty list. 1004 // Else, we map back the output to the original x coordinate. 1005 if(size(ib) == 0) 1006 { 1007 return(list()); 1008 } else 1009 { 1010 for(i = 1; i <= size(ib[1]); i++) 1011 { 1012 ib[1][i] = moveFromVar(ib[1][i], px, x); 1013 } 1014 ib[2] = moveFromVar(ib[2], px, x); 1015 return(ib); 1016 } 1017 } 1018 } 1019 1020 // This is the general case of non-rational coordinates. 1021 if((deg(px) > 1) or (deg(py, vy) > 1)) 1022 { 1023 dbprint(dbg, "Case: non-rational xy-coordinates."); 1024 // If needed, we make a coord change so that y in terms of x has 1025 // degree 1. 1026 1027 poly fCh = f; 1028 1029 if(deg(py,vy) > 1) 1030 { 1031 // The degree in y is > 1, hence there are singularities with 1032 // the same x-coordinate. 1033 dbprint(dbg, "Conjugated singularities with same x-coordinate."); 1034 dbprint(dbg, "Linear coordinate change needed."); 1035 1036 li = 1; 1037 poly linCh = x; 1038 poly invCh = x; 1039 ideal PCh = P; 1040 while(((li < 20) and (deg(py,vy) > 1)) or (isXMonic(f)==0)){ 1041 linCh = linCh + y; 1042 invCh = invCh - y; 1043 fCh = subst(f, x, x + y); 1044 PCh = subst(PCh, x, x + y); 1045 PLex = yInTermOfx(PCh); 1046 px = PLex[1]; 1047 py = PLex[size(PLex)]; 1048 li++; 1049 } 1050 1051 if(li == 20){ 1052 // No appropiate coordinate change was found. We return an empty 1053 // list. 1054 "No appropiate coordinate change found. Procedure failed."; 1055 return(list()); 1056 } else 1057 { 1058 dbprint(dbg, "Coordinate change applied: x ->", linCh); 1059 } 1060 fCh = monic(fCh); 1061 py = monic(py); 1062 } else 1063 { 1064 dbprint(dbg, "No conjugated singularities with same x-coordinate."); 1065 dbprint(dbg, "No coordinate change needed."); 1066 } 1067 dbprint(dbg, ""); 1068 1069 // We compute the integral basis. 1070 list ib = ibNonRatXY(fCh, px, py, locBasis); 1071 1072 if(li > 0) 1073 { 1074 dbprint(dbg, "Integral basis for the transformed polynomial: "); 1075 dbprint(dbg, ib); 1076 dbprint(dbg, "px: ", px); 1077 dbprint(dbg, "py: ", py); 1078 dbprint(dbg, "invch: ", invCh); 1079 } 1080 1081 // If we applied a linar coordinate change, we apply the inverse 1082 // transformation 1083 if(li > 0) 1084 { 1085 for(i = 1; i <= size(ib); i++){ 1086 ib[i][1] = subst(ib[i][1], x, invCh); 1087 } 1088 px = subst(px, x, invCh); 1089 1090 } 1091 1092 dbprint(dbg, "ibLocal - Convert to integral basis shape: ", ib, px); 1093 1094 ib = convertIB(ib, px); 1095 1096 1097 if(li > 0) 1098 { 1099 ib = normToIntJacob(ib[1], ib[2], y, f); 1100 } 1101 1102 dbprint(dbg, "ibLocal - Output of convertIB: ", ib, px); 1103 1104 return(ib); 1105 } 1106 1107 // Case of rational coordinates. 1108 if(deg(py)*deg(px) == 1){ 1109 dbprint(dbg, "Case: rational coordinates."); 1110 1111 // Hensel algorithm is used in this case. 1112 moved = 0; 1113 if((px != x) || (py != y)) 1114 { 1115 fT = moveTo(f, px, py); 1116 moved = 1; 1117 } else 1118 { 1119 fT = f; 1120 } 1121 1122 ideal ibN = ibAt0(fT, locBasis); 1123 1124 if(size(ibN) == 0){ 1125 return(list()); 1126 } else { 1127 if(moved == 1) 1128 { 1129 for(i = 1; i <= size(ibN); i++){ 1130 ibN[i] = moveFrom(ibN[i], px, py); 1131 } 1132 } 1133 list ib = list(ibN, ibN[1]); 1134 return(ib); 1135 } 1136 } 1137 } 1138 1139 //////////////////////////////////////////////////////////////////////// 1140 // 1141 // Procs for handling different kind of singularities 1142 // 1143 //////////////////////////////////////////////////////////////////////// 1144 1145 // Computes the integral basis of R[y]/f, with R = k[x] localized at x=0. 1146 // It uses the algorithm by Boehm, Decker, Laplagne, Pfister. 1147 // If locBasis = 1, it doesnt take into account the the unit from f 1148 // after localization 1149 static proc ibAt0(poly f, int locBasis) 1150 { 1151 int t; 1152 int dbg = printlevel - voice + 4; 1153 1154 int tt = timer; 1155 1156 poly outComp; // The component outside the origin. 1157 list b; 1158 1159 def R = basering; 1160 int slN, slD, bestSl; 1161 int i, j, k; 1162 1163 intvec vy = (0,1); 1164 intvec vx = (1,0); 1165 poly x = var(1); 1166 poly y = var(2); 1167 int n = deg(f, vy); 1168 1169 // Degree of the component outside the origin 1170 poly f0 = subst(f, var(1), 0); 1171 int d0 = divideBy(f0, var(2))[2]; 1172 int d1 = n - d0; 1173 1174 debug_log_intbas(3, "------Time preliminars: ", timer - tt); 1175 tt = timer; 1176 1177 // Starting exponents and minimal polynomials of the Puiseux expansions 1178 1179 // Puiseux expansions at the origin 1180 dbprint(dbg, "--Computing Puiseux expansions at the origin..."); 1181 1182 1183 1184 // puiseux(poly f, int maxDeg, int atOrigin) 1185 list l = puiseux(f, -1, 1); 1186 //"puiseux expansion: ", l; 1187 //~; 1188 1189 debug_log_intbas(3, "------Time puiseux expansions: ", timer - tt); 1190 tt = timer; 1191 1192 int totDeg = getTotalDeg(l); 1193 list classes = getClasses(l); 1194 1195 //if(dbg > 5) 1196 //{ 1197 // "Puiseux branches: "; classes; 1198 //} 1199 1200 // We compute the building blocks of the basis elements 1201 dbprint(dbg, "--Building factors of different degrees..."); 1202 list bF = buildFactors(classes); 1203 //"Factors: "; bF; 1204 1205 debug_log_intbas(3, "------Time for the factors: ", timer - tt); 1206 tt = timer; 1207 1208 list slopes = getSlopes(classes); 1209 intvec md = getDegs(classes); 1210 1211 // Tables of vanishing order of diferences of puiseux expansions 1212 dbprint(dbg, "--Computing vanishing orders..."); 1213 matrix M = valIK(classes); 1214 list vS = valIKSelf(bF, md); 1215 list MSelf = vS[1]; 1216 1217 list bestElem = vS[2]; 1218 1219 // The highest exponent of the denominator 1220 if(size(classes) > 1) 1221 { 1222 b = ibElement(M, MSelf, d0 - 1, md); 1223 number maxExp = b[1]; 1224 intvec elem = b[2]; 1225 } else 1226 { 1227 if(d0 > 1) 1228 { 1229 number maxExp = MSelf[1][size(MSelf[1])]; 1230 intvec elem = d0-1; 1231 } else { 1232 // This should never happen, unless we have a non-singular point? 1233 number maxExp = 0; 1234 intvec elem = 0; 1235 } 1236 } 1237 1238 debug_log_intbas(3, "------Time for factors info: ", timer - tt); 1239 tt = timer; 1240 1241 dbprint(dbg, "--Building HenselBlocks..."); 1242 int degExpand = int(maxExp); 1243 dbprint(dbg, "---- Degree of expansions: ", degExpand); 1244 1245 1246 // Computing hensel blocks... 1247 list I2Lifted = henselBlocks(f, degExpand, 1); 1248 debug_log_intbas(3, "------Time Hensel Blocks: ", timer - tt); 1249 tt = timer; 1250 1251 1252 //////////////////////////////////////////////////////////////////////// 1253 // RECOMPUTE CLASSES USING HENSEL BLOCKS 1254 // SO THAT THEY ARE COMPUTED IN THE SAME ORDER 1255 1256 // FIX THIS SO THAT THEY ARE ALWAYS COMPUTED IN THE SAME ORDER AS 1257 // THE HENSEL BLOCKS 1258 1259 // if((size(classes) > 1) && (1==0)) 1260 if((size(classes) > 1)) 1261 { 1262 list classesNew; 1263 list classesTemp; 1264 for(i = 1; i <= size(I2Lifted)-1; i++) 1265 { 1266 //l = puiseux(I2Lifted[i+1], -1, 1); 1267 // This is slower, many unneeded terms, we should develop only 1268 // until they become different. FIX! 1269 // (or even better, dont recompute but correct blocks in the correct order!) 1270 //l = puiseux(I2Lifted[i+1], degExpand, 1); 1271 l = puiseux(I2Lifted[i+1], -1, 1); 1272 classesTemp = getClasses(l); 1273 classesNew = classesNew + classesTemp; 1274 } 1275 1276 classes = classesNew; 1277 1278 dbprint(dbg, "Building factors of different degrees..."); 1279 bF = buildFactors(classes); 1280 1281 slopes = getSlopes(classes); 1282 md = getDegs(classes); 1283 1284 // Tables of vanishing order of diferences of puiseux expansions 1285 dbprint(dbg, "Computing vanishing orders..."); 1286 M = valIK(classes); 1287 1288 vS = valIKSelf(bF, md); 1289 MSelf = vS[1]; 1290 1291 bestElem = vS[2]; 1292 1293 debug_log_intbas(3, "------Time for recomputation: ", timer - tt); 1294 tt = timer; 1295 } 1296 1297 // RECOMPUTATION FINISHED 1298 /////////////////////////////////////////////////////////////////////// 1299 1300 //dbprint(dbg, "Output of Hensel Blocks: "); 1301 //dbprint(dbg, I2Lifted); 1302 1303 int cl; 1304 1305 int nClasses; 1306 nClasses = size(classes); 1307 1308 // ordsFull gives the order of each polynomial in I2Lifted at the other conjugacy classes. 1309 matrix ordsFull[size(I2Lifted) -1][nClasses]; 1310 1311 for(i = 1; i <= size(I2Lifted) - 1; i++) 1312 { 1313 for(cl = 1; cl <= nClasses; cl++) 1314 { 1315 if(i != cl) 1316 { 1317 ordsFull[i, cl] = ordAtPol(I2Lifted[i+1], classes[cl][1]); 1318 } 1319 } 1320 } 1321 1322 debug_log_intbas(3, "------Time for ordFull: ", timer - tt); 1323 tt = timer; 1324 1325 list ordsBest; 1326 list ordsTemp; 1327 for(cl = 1; cl <= nClasses; cl++) 1328 { 1329 ordsBest[cl] = list(); 1330 for(i = 1; i <= size(bestElem); i++) 1331 { 1332 ordsTemp = list(); 1333 for(j = 1; j <= size(bestElem[i]); j++) 1334 { 1335 ordsTemp[j] = ordAtPol(bestElem[i][j], classes[cl][1]); 1336 } 1337 ordsBest[cl][i] = ordsTemp; 1338 } 1339 } 1340 1341 debug_log_intbas(3, "------Time for ordsBest: ", timer - tt); 1342 1343 tt = timer; 1344 1345 int mdm = 0; 1346 int mdmTemp; 1347 1348 for(i = 1; i <= nClasses; i++) 1349 { 1350 mdmTemp = maxDegMerge(n, i, locBasis, d0, M, MSelf, md, classes, I2Lifted, bestElem, ordsFull, ordsBest); 1351 //"mdmTemp = ", mdmTemp; 1352 mdm = maxInt(mdm, mdmTemp); 1353 } 1354 tt = timer; 1355 1356 if(printlevel - voice > 0) 1357 { 1358 "Maximum degree required for merging: ", mdm; 1359 } 1360 1361 list ifOut = irreducibleFactors(f, classes, mdm); 1362 list I2LiftedFull = ifOut[1]; 1363 1364 if((ifOut[4] == 1)) // Wrong number of factors, recompute orders 1365 { 1366 kill ordsFull; 1367 kill ordsBest; 1368 kill ordsTemp; 1369 1370 matrix ordsFull[size(I2LiftedFull) -1][nClasses]; 1371 1372 for(i = 1; i <= size(I2LiftedFull) - 1; i++) 1373 { 1374 for(cl = 1; cl <= nClasses; cl++) 1375 { 1376 if(i != cl) 1377 { 1378 ordsFull[i, cl] = ordAtPol(I2LiftedFull[i+1], classes[cl][1]); 1379 } 1380 } 1381 } 1382 1383 debug_log_intbas(3, "------Time for ordFull: ", timer - tt); 1384 tt = timer; 1385 1386 list ordsBest; 1387 list ordsTemp; 1388 for(cl = 1; cl <= nClasses; cl++) 1389 { 1390 ordsBest[cl] = list(); 1391 for(i = 1; i <= size(bestElem); i++) 1392 { 1393 ordsTemp = list(); 1394 for(j = 1; j <= size(bestElem[i]); j++) 1395 { 1396 ordsTemp[j] = ordAtPol(bestElem[i][j], classes[cl][1]); 1397 } 1398 ordsBest[cl][i] = ordsTemp; 1399 } 1400 } 1401 } 1402 1403 if(ifOut[3] == 0) 1404 { 1405 "Classes are wrongly computed. We need to recompute!"; 1406 1407 list mergeCl = mergeClassesIF(f, classes, ifOut, mdm); 1408 classes = mergeCl[1]; 1409 ifOut = mergeCl[2]; 1410 1411 slopes = getSlopes(classes); 1412 md = getDegs(classes); 1413 1414 ifOut = irreducibleFactors(f, classes, mdm); 1415 if(ifOut[3] == 0) 1416 { 1417 "Recomputation unsuccesfull. Output may be wrong."; 1418 } else 1419 { 1420 "Recomputation succesfull. "; 1421 } 1422 I2LiftedFull = ifOut[1]; 1423 1424 // Check if needed or can be obtained from I2LiftedFull 1425 bF = buildFactors(classes); 1426 1427 // Recomputation of classes info 1428 // Code should be reused 1429 1430 // Tables of vanishing order of diferences of puiseux expansions 1431 dbprint(dbg, "Computing vanishing orders..."); 1432 M = valIK(classes); 1433 vS = valIKSelf(bF, md); 1434 MSelf = vS[1]; 1435 1436 bestElem = vS[2]; 1437 1438 nClasses = size(classes); 1439 1440 kill ordsFull, ordsBest, ordsTemp; 1441 1442 matrix ordsFull[size(I2Lifted) -1][nClasses]; 1443 list ordsBest; 1444 list ordsTemp; 1445 1446 for(i = 1; i <= size(I2LiftedFull) - 1; i++) 1447 { 1448 for(cl = 1; cl <= nClasses; cl++) 1449 { 1450 if(i != cl) 1451 { 1452 ordsFull[i, cl] = ordAtPol(I2LiftedFull[i+1], classes[cl][1]); 1453 } 1454 } 1455 } 1456 1457 for(cl = 1; cl <= nClasses; cl++) 1458 { 1459 ordsBest[cl] = list(); 1460 for(i = 1; i <= size(bestElem); i++) 1461 { 1462 ordsTemp = list(); 1463 for(j = 1; j <= size(bestElem[i]); j++) 1464 { 1465 ordsTemp[j] = ordAtPol(bestElem[i][j], classes[cl][1]); 1466 } 1467 ordsBest[cl][i] = ordsTemp; 1468 } 1469 } 1470 1471 //debug_log_intbas(3, "------Time for recomputation: ", timer - tt); 1472 } 1473 1474 for(i = 1; i <= size(I2LiftedFull); i++) 1475 { 1476 I2LiftedFull[i] = reduce(I2LiftedFull[i], groebner(var(1)^mdm)); 1477 } 1478 1479 ideal IOut; 1480 list outNormal; 1481 list bases; 1482 1483 list IdOut; 1484 1485 list l1, l2; 1486 1487 tt = timer; 1488 1489 for(i = 1; i <= nClasses; i++) 1490 { 1491 // Computing ~A(i)_new... (using modified chinese remainder) 1492 IdOut[i] = locLocAlgorithm(n, i, locBasis, d0, M, MSelf, md, classes, I2LiftedFull, mdm, bestElem, ordsFull, ordsBest); 1493 bases = bases + list(IdOut[i]); 1494 } 1495 debug_log_intbas(3, "------Time integral basis for all branches: ", timer - tt); 1496 1497 if(nClasses > 1) 1498 { 1499 // We add some extra polynomials to the integral basis 1500 // which will simplify the computations 1501 list enzNum; 1502 list enzDen; 1503 poly elemNum; 1504 number euNum; 1505 int eu; 1506 intvec classesInd = 1:nClasses; 1507 number ordY = ordAtClassesPol(var(2), classes, classesInd); 1508 for(k = 0; k < n - deg(I2Lifted[1], vy); k++) 1509 { 1510 elemNum = var(2)^k; 1511 euNum = ordY * k; 1512 eu = int(euNum); 1513 enzNum = enzNum + list(elemNum); 1514 enzDen = enzDen + list(var(1)^(eu)); 1515 } 1516 list enzOut = comDen(enzNum, enzDen); 1517 ideal enzId = enzOut[2]; 1518 for(k=1; k <=size(enzOut[1]); k++) 1519 { 1520 enzId[k+1] = enzOut[1][k]; 1521 } 1522 list enzOutList = enzId, enzId[1]; 1523 bases = bases + list(enzOutList); 1524 } 1525 1526 1527 tt = timer; 1528 if(size(bases) > 1) 1529 { 1530 // We compute the local integral basis at the origin 1531 dbprint(dbg, "--Merging the integral bases for the branches..."); 1532 outNormal = mergeBases(bases); 1533 1534 // Check the correct degree for reduction 1535 //outNormal[1] = reduce(outNormal[1], groebner(x^mdm)); 1536 1537 1538 //dbprint(dbg, "----Computing the groebner basis...", outNormal[1]); 1539 //dbprint(dbg, "----Denominator:", outNormal[2]); 1540 outNormal[1] = groebner(outNormal[1]); 1541 dbprint(dbg, "----Merging finished"); 1542 poly fLoc = 1; 1543 for(k = 2; k <= size(I2LiftedFull); k++) 1544 { 1545 fLoc = reduce(fLoc * reduce(I2LiftedFull[k], groebner(x^mdm)), groebner(x^mdm)); 1546 } 1547 int needGroeb = 1; 1548 list intBas = normToInt(fLoc, outNormal[1], outNormal[2], needGroeb); 1549 } else 1550 { 1551 list intBas; 1552 intBas[1] = bases[1][1]; 1553 intBas[2] = bases[1][2]; 1554 } 1555 debug_log_intbas(3, "------Time for merging bases: ", timer - tt); 1556 1557 1558 // We add the unit outside the origin 1559 for(k = 0; k < deg(I2LiftedFull[1], vy); k++) 1560 { 1561 IOut[k+1] = intBas[2]*var(2)^(k); 1562 } 1563 for(k = 1; k <= size(intBas[1]); k++) 1564 { 1565 IOut[size(IOut)+1] = intBas[1][k] * I2Lifted[1]; 1566 } 1567 1568 return(IOut); 1569 } 1570 1571 //////////////////////////////////////////////////////////////////////// 1572 1573 // Computation of the local integral basis at a point with non-rational 1574 // coordinates. We assume that the singularities have no repeated x-coordinate. 1575 // px is a polynomial in the first variable. The roots of px are the 1576 // x-coordinates of the singularities. 1577 // py is a polynomial of degree 1 in y, giving the y-coordinate of the 1578 // singularities. 1579 // locBasis indicates if a local basis is needed. 1580 static proc ibNonRatXY(poly f, poly px, poly py, int locBasis) 1581 { 1582 int i; 1583 def R = basering; 1584 1585 // We add a root of px to the basering. 1586 // It will be the x-coordinate of the singularity. 1587 1588 def S = splitRingAt(px); 1589 setring S; 1590 poly x = var(1); 1591 poly y = var(2); 1592 poly f = imap(R, f); 1593 poly px = imap(R, px); 1594 poly py = imap(R, py); 1595 1596 // We compute the y-coordinate of the singularity 1597 poly pya = subst(py,x,par(1)); 1598 1599 // We move the singularity to the origin and compute the integral basis 1600 poly fT = moveTo(f, var(1) - par(1), pya); 1601 1602 //ideal IOut = ibOrigin(fT, locBasis); 1603 ideal IOut = ibAt0(fT, locBasis); 1604 1605 list ib = intBasIdealToList(IOut); 1606 1607 dbprint(dbg, "ibNonRatXY - Integral basis at the origin: ", ib); 1608 1609 1610 // The output might contain the root added, and we have to remove it. 1611 for(i = 1; i <= size(ib); i++){ 1612 // We move back the singularity to original position. 1613 ib[i][1] = moveFrom(ib[i][1], var(1) - par(1), pya); 1614 1615 // We remove the parameter from the denominator. 1616 // To achieve this, we reduce the polynomial modulo the generators 1617 // of smaller degree. 1618 // Note that the simple version ib[i][1] = subst(ib[i][1], par(1), x) 1619 // does not work in general. 1620 if(ib[i][2] > 0) 1621 { 1622 // "Call to elimPar"; 1623 // ib; 1624 // ~; 1625 ib[i][1] = elimPar(ib, i); 1626 } else 1627 { 1628 // When there is no denominator we can simply replace the parameter by 0. 1629 ib[i][1] = subst(ib[i][1], par(1), 0); 1630 } 1631 } 1632 1633 dbprint(dbg, "ibNonRatXY - Integral basis after moving back to the original singularity: ", ib); 1634 1635 // We map back the output to the original ring. 1636 setring R; 1637 list ib = imap(S, ib); 1638 return(ib); 1639 } 1640 1641 //////////////////////////////////////////////////////////////////////// 1642 1643 // Input: a list of different normalization bases, where the first 1644 // element of each basis is the denominator 1645 // Output: it computes a common denominator for all the bases, and 1646 // returns a Groebner basis of the ideal generated by all the 1647 // numerators with this common denominator. 1648 static proc mergeBases(list bases) 1649 { 1650 int i; 1651 poly den = 1; 1652 ideal I; 1653 ideal IT; 1654 for(i = 1; i <= size(bases); i++) 1655 { 1656 den = lcm(den, bases[i][2]); 1657 } 1658 for(i = 1; i <= size(bases); i++) 1659 { 1660 IT = bases[i][1] * (den / bases[i][2]); 1661 I = I + IT; 1662 } 1663 list out = I, den; 1664 return(out); 1665 } 1666 1667 //////////////////////////////////////////////////////////////////////// 1668 1669 //////////////////////////////////////////////////////////////////////// 1670 // 1671 // MAIN PROCEDURE OF THE NEW APPROACH AS EXPLAINED IN THE 1672 // PAPER by Boehm, Decker, Laplagne & Pfister 1673 // 1674 //////////////////////////////////////////////////////////////////////// 1675 1676 // Input: n is the degree of f 1677 // cl is the index of the class for which the loc basis is computed. 1678 // Output: integral basis for the branches at the origin 1679 // Algorithm: combines the integral basis of each conjugacy class of expansions. 1680 static proc locLocAlgorithm(int n, int cl, int locBasis, int d0, matrix M, list MSelf, intvec md, list classes, list I2Lifted, int mdm, list bestElem, matrix ordsFull, list ordsBest); 1681 { 1682 if(printlevel - voice > 0) 1683 { 1684 ""; 1685 "-- Starting computation of lifted integral basis for class ", cl; 1686 } 1687 1688 int tim = timer; 1689 def R = basering; 1690 1691 int i, j, k; 1692 list ibNum, ibDen; 1693 number expUnit; // The integrality exponent of the local unit 1694 poly polyUnit; 1695 1696 intvec vy = (0,1); 1697 intvec vx = (1,0); 1698 1699 // The elements containing the expansions that vanish outside the origin, 1700 // but not the locloc unit 1701 for(k = 0; k < (n - md[cl] - deg(I2Lifted[1], vy)); k++) 1702 { 1703 ibNum = ibNum + list(var(2)^k); 1704 ibDen = ibDen + list(1); 1705 } 1706 1707 poly baseFactor; 1708 number expBaseFactor; 1709 poly locLocFactor = 1; 1710 expUnit = 0; 1711 1712 def SS = classes[cl][1]; 1713 1714 // This corrects for some wrongly computed number of classes 1715 int nClasses; 1716 // if(size(classes) > size(I2Lifted) - 1) 1717 // { 1718 // nClasses = size(I2Lifted) - 1; 1719 // } else 1720 // { 1721 // nClasses = size(classes); 1722 // } 1723 nClasses = size(classes); 1724 1725 // We add factors to merge the integral bases for the branches 1726 // applying Algorithm "Merge Coefficients" 1727 if(nClasses > 1) 1728 { 1729 for(j = 1; j <= size(I2Lifted)-1; j++) 1730 { 1731 if(j != cl) 1732 { 1733 expUnit = expUnit + number(ordsFull[j, cl]); 1734 locLocFactor = prodMod(locLocFactor, I2Lifted[1 + j], mdm+1); 1735 } 1736 } 1737 // The first term containing the locloc unit 1738 expBaseFactor = expUnit; 1739 1740 // If the order of hi is not integer, we add a factor. 1741 // The order of hi is expBaseFactor 1742 // The order of y is MSelf[cl][1] 1743 if(int(denominator(expBaseFactor)) > 1) 1744 { 1745 // We add the factor corresponding to the full expansions 1746 list fullPoly; 1747 for(j = 1; j <= nClasses; j++) 1748 { 1749 fullPoly[j] = I2Lifted[j+1]; 1750 } 1751 1752 int whichElem = 0; 1753 int den1; 1754 int den2; 1755 1756 intvec degsCl; 1757 for(i = 1; i <= size(MSelf); i++) 1758 { 1759 degsCl[i] = size(MSelf[i]) + 1; 1760 } 1761 intvec chVec = 0:size(MSelf); 1762 1763 den1 = 1; 1764 den2 = int(denominator(expBaseFactor)); 1765 1766 number ordNewFactor; 1767 1768 number oAP; 1769 number oAPTemp; 1770 1771 while(den1 mod den2 != 0) 1772 { 1773 chVec = nextSummand(degsCl, chVec, cl); 1774 1775 ordNewFactor = 0; 1776 for(i = 1; i <= nClasses; i++) 1777 { 1778 if(i != cl) 1779 { 1780 k = chVec[i]; 1781 if(k > 0) 1782 { 1783 if(k <= size(bestElem[i])) 1784 { 1785 oAP = number(ordsBest[cl][i][k]); 1786 ordNewFactor = ordNewFactor + oAP; 1787 } else 1788 { 1789 oAP = number(ordsFull[i, cl]); 1790 ordNewFactor = ordNewFactor + oAP; 1791 } 1792 } 1793 } 1794 } 1795 den1 = int(denominator(ordNewFactor)); 1796 } 1797 1798 poly newFactor = 1; 1799 int denNewFactor = den1; 1800 int powFactor = 0; 1801 1802 for(i = 1; i <= size(MSelf); i++) 1803 { 1804 k = chVec[i]; 1805 if(k > 0) 1806 { 1807 if(k <= size(bestElem[i])) 1808 { 1809 newFactor = prodMod(newFactor, bestElem[i][k], mdm); 1810 } else 1811 { 1812 newFactor = prodMod(newFactor, fullPoly[i], mdm); 1813 } 1814 } 1815 } 1816 1817 int nnE = int(numerator(expBaseFactor)); 1818 int ddE = int(denominator(expBaseFactor)); 1819 int nnY = int(numerator(ordNewFactor)); 1820 1821 while(ddE > 1) 1822 { 1823 powFactor = powFactor + 1; 1824 expBaseFactor = expUnit + powFactor * ordNewFactor; 1825 ddE = int(denominator(expBaseFactor)); 1826 } 1827 baseFactor = prodMod(locLocFactor, newFactor^powFactor, mdm); 1828 1829 if(printlevel - voice >= 0) 1830 { 1831 "----Coefficient for merging for class i = ", cl, " (as in Algorithm 7) developed up to order X^" , mdm; 1832 "------beta_i = ", newFactor, "^", powFactor; 1833 "------h_i = ", locLocFactor; 1834 "------c_i = ", expBaseFactor; 1835 } 1836 } else 1837 { 1838 baseFactor = locLocFactor; 1839 if(printlevel - voice >= 0) 1840 { 1841 "----Coefficient for merging for class i = ", cl, " (as in Algorithm 7) developed up to order X^" , mdm; 1842 "------beta_i = ", 1; 1843 "------h_i = ", locLocFactor; 1844 "------c_i = ", expBaseFactor; 1845 } 1846 1847 } 1848 } else 1849 { 1850 baseFactor = 1; 1851 expBaseFactor = 0; 1852 } 1853 // The initial element 1854 ibNum = ibNum + list(baseFactor); 1855 ibDen = ibDen + list(var(1)^int(expBaseFactor)); 1856 1857 // We put everything together in integral basis shape 1858 poly elemNum; 1859 int eu; 1860 number euNum; 1861 for(k = (n - md[cl] + 2); k <= n; k++) 1862 { 1863 euNum = expBaseFactor + MSelf[cl][k - (n-md[cl]+1)]; 1864 eu = int(euNum); 1865 elemNum = prodMod(baseFactor, bestElem[cl][k - (n-md[cl]+1)], mdm); 1866 ibNum = ibNum + list(elemNum); 1867 ibDen = ibDen + list(var(1)^(eu)); 1868 } 1869 1870 ideal IOut; 1871 for(i = 1; i<=size(ibNum); i++) 1872 { 1873 IOut[i] = (ibNum[i] * ibDen[size(ibDen)]) / ibDen[i]; 1874 } 1875 1876 list outp = IOut, ibDen[size(ibDen)]; 1877 1878 // We can reduce modulo the denominator 1879 //outp[1] = reduce(outp[1], groebner(outp[2])); 1880 1881 // if(printlevel - voice >= 0) 1882 // { 1883 // "---- Output: "; outp; 1884 // //~; 1885 // ""; 1886 // } 1887 1888 1889 return(outp); 1890 } 1891 1892 //////////////////////////////////////////////////////////////////////// 1893 1894 // Computes the smallest slope of the list of slopes. 1895 static proc getSlope(list slopes) 1896 { 1897 int i; 1898 int slN = 1; 1899 int slD = 0; 1900 int bestI; 1901 for(i = 1; i <= size(slopes); i++) 1902 { 1903 if(slopes[i][1]*slD < slN * slopes[i][2]) 1904 { 1905 slN = slopes[i][1]; 1906 slD = slopes[i][2]; 1907 bestI = i; 1908 } 1909 } 1910 return(list(slN, slD, bestI)); 1911 } 1912 1913 //////////////////////////////////////////////////////////////////////// 1914 1915 1916 // Local factors at the origin of the original polynomial f. 1917 // Input: a list whose elements are classes of conjugate Puiseux 1918 // expansions, as returned by proc getClasses. 1919 // Output: a list of lists of three elements. 1920 // The first element in the i-th list is a list of the factors 1921 // corresponding to the i-th conjugacy class developed up to the 1922 // different degrees corresponding to the different possible 1923 // truncations of the puiseux expansions. 1924 // The second element is a list of the orders of the corresponding 1925 // factors. 1926 // The third element is a list of the degrees of the corresponding 1927 // factors. 1928 static proc buildFactors(list classes) 1929 { 1930 int i, j; 1931 int d = -1; 1932 int ind; 1933 int first; 1934 int k; 1935 int stop1; 1936 1937 int dbg = printlevel - voice + 4; 1938 1939 intvec exps; 1940 intvec expsT; 1941 1942 int t; // Timings 1943 1944 intvec vx = (1,0); 1945 intvec vy = (0,1); 1946 1947 def R = basering; 1948 list facs; 1949 list ords; 1950 list degs; 1951 list gfChecks; 1952 int den; 1953 list fFrac; 1954 poly fGround; 1955 def S; 1956 1957 list polyGround; 1958 1959 int isGround = 1; 1960 1961 for(i = 1; i <= size(classes); i++) 1962 { 1963 facs[i] = list(); 1964 ords[i] = list(); 1965 degs[i] = list(); 1966 gfChecks[i] = list(); 1967 1968 ind = 1; 1969 first = 1; 1970 stop1 = 0; 1971 1972 // If there is only one expansion in the class, there is nothing to do 1973 if((typeof(classes[i][1]) == "ring") or (size(classes[i]) > 1)) 1974 { 1975 for(j = 1; j <= size(classes[i]); j++) 1976 { 1977 if(typeof(classes[i][j]) == "ring") 1978 { 1979 S = classes[i][j]; 1980 setring S; 1981 if(typeof(PE[1][7])!= "none") 1982 { 1983 1984 debug_log_intbas(6, "Computation of the characterisitic exponents from the integral basis. Check if correct or characteristic orders are needed."); 1985 1986 //expsT = poly2intvec(PE[1][1]); 1987 //"Check expsT 1: ", expsT; 1988 expsT = list2intvec(PE[1][7]); 1989 //"Check expsT 2: ", expsT; 1990 //"Compare exps: "; 1991 //poly2intvec(PE[1][1]); 1992 //charExp(poly2intvec(PE[1][1]), PE[1][2]); 1993 //expsT; 1994 } else 1995 { 1996 expsT = deg(PE[1][1]); 1997 } 1998 if(j == 1) 1999 { 2000 den = PE[1][2]; 2001 } 2002 setring R; 2003 } else 2004 { 2005 if(typeof(classes[i][j][7]) != "none") 2006 { 2007 expsT = list2intvec(classes[i][j][7]); 2008 } else 2009 { 2010 expsT = deg(classes[i][j][1]); 2011 } 2012 if(j == 1) 2013 { 2014 den = classes[i][1][2]; 2015 } 2016 } 2017 if(j > 1) 2018 { 2019 exps = appendIntvecs(exps, expsT); 2020 } else 2021 { 2022 exps = expsT; 2023 } 2024 } 2025 2026 for(k = 1; k <= size(exps); k++) 2027 { 2028 d = exps[k]; 2029 if(dbg >= 2) 2030 { 2031 "----Building factor of degree < d = ", d; 2032 } 2033 t = timer; 2034 for(j = 1; j <= size(classes[i]); j++) 2035 { 2036 if(typeof(classes[i][j]) == "ring") 2037 { 2038 if(!defined(dMP)) 2039 { 2040 int dMP; 2041 } 2042 dMP = pardeg(minpoly); 2043 S = classes[i][j]; 2044 2045 setring S; 2046 // d = -1 for computing polynomial of full degree 2047 if(d >= 0){ 2048 poly fF = jet(PE[1][1], d-1, vx); 2049 } else 2050 { 2051 poly fF = PE[1][1]; 2052 } 2053 if(dMP > 1) 2054 { 2055 poly mp = composePolys(minPolys); 2056 poly mpX = subst(mp, var(2), var(1)); 2057 poly fFB = buildPolyFracNew(fF, mpX); 2058 ideal rel = extendBack(fFB, erg[1], dMP); 2059 matrix CC = coef(fFB, var(1)*var(2)); 2060 } else 2061 { 2062 poly fFB = buildPolyFrac(fF); 2063 } 2064 setring R; 2065 2066 if(dMP > 1) 2067 { 2068 ideal rel = imap(S, rel); 2069 matrix CC = imap(S, CC); 2070 int kk; 2071 fFrac[j] = 0; 2072 for(kk = 1; kk <= ncols(CC); kk++) 2073 { 2074 fFrac[j] = fFrac[j] + subst(rel[kk], var(1), par(1)) * CC[1, kk]; 2075 } 2076 } else 2077 { 2078 fFrac[j] = imap(S, fFB); 2079 } 2080 2081 // Cleaning 2082 setring S; 2083 kill fF; 2084 kill fFB; 2085 setring R; 2086 } else 2087 { 2088 if(d>=0){ 2089 fFrac[j] = var(2) - jet(classes[i][j][1], d-1, vx); 2090 } else 2091 { 2092 fFrac[j] = var(2) - classes[i][j][1]; 2093 } 2094 2095 } 2096 } 2097 2098 polyGround = buildPolyGround(fFrac, den); 2099 2100 fGround = squarefree(polyGround[1]); 2101 if (polyGround[2] == 0) 2102 { 2103 // "Error. Conjugation classes are wrongly computed. The polynomial obtained is not over the ground field. "; 2104 ind++; 2105 isGround = 0; 2106 } else { 2107 2108 debug_log_intbas(4, "------Time for this factor: ", timer - t); 2109 if(dbg - 1 > 0) 2110 { 2111 "------Factor: ", fGround; 2112 } 2113 2114 fFrac = list(); 2115 2116 // If the degree has not increased, we replaced the previous one. 2117 // Else, we add it to the list. 2118 if(first != 1) 2119 { 2120 if(deg(fGround, vy) > degs[i][ind]) 2121 { 2122 ind++; 2123 } else 2124 { 2125 dbprint(dbg - 1, "Factor discarded"); 2126 } 2127 } else 2128 { 2129 first = 0; 2130 } 2131 } 2132 facs[i][ind] = fGround; 2133 if(d>=0){ 2134 ords[i][ind] = number(d) / number(den); 2135 } else { 2136 ords[i][ind] = number(deg(facs[i][ind],vx)) / number(den); 2137 } 2138 degs[i][ind] = deg(fGround, vy); 2139 gfChecks[i][ind] = polyGround[2]; 2140 2141 } 2142 } 2143 } 2144 return(list(facs, ords, degs, gfChecks, isGround)); 2145 } 2146 2147 //////////////////////////////////////////////////////////////////////// 2148 2149 // Product of conjugate factors 2150 // Input: a polynomial f over an algebraic extension of the base ring. 2151 // the minimal polynomial mp as a polynomial in the first variable 2152 // (it can be different from the minpoly of the ring, since we can be 2153 // working on an extension of an extension) 2154 // Output: polynomial = the product of (y-f_i) for all conjugate polynomials 2155 // f_i of f. 2156 static proc buildPolyFracNew(poly f, poly mp) 2157 { 2158 int i; 2159 def R = basering; 2160 int d = deg(mp, intvec(1,0)); 2161 def Q = ring(0, (var(1), var(2), @a, T(1..d)), lp); 2162 ring S = 0, (var(1), @a), dp; 2163 poly f = imap(R, f); 2164 intvec da = (0,1); 2165 if(deg(f, da) > 0) 2166 { 2167 //poly mp = imap(R, mp); 2168 //mp = subst(mp,var(1),@a); 2169 setring Q; 2170 poly f = imap(R, f); 2171 poly mp = imap(R, mp); 2172 mp = mp / leadcoef(mp); 2173 poly fNew; 2174 poly fNewTemp = 1; 2175 poly rels = 1; 2176 ideal I; 2177 for(i = 1; i <= d; i++) 2178 { 2179 rels = rels * (var(1) - T(i)); 2180 } 2181 matrix c1 = coeffs(rels, var(1)); 2182 matrix c2 = coeffs(mp, var(1)); 2183 for(i = 1; i<=d; i++) 2184 { 2185 I[i] = c1[i,1] - c2[i,1]; 2186 } 2187 I = groebner(I); 2188 2189 int t = timer; 2190 poly fTemp; 2191 for(i = 1; i<=d; i++) 2192 { 2193 fTemp = subst(f, var(3), T(i)); 2194 fNewTemp = fNewTemp * (var(2) - fTemp); 2195 fNew = reduce(fNewTemp, I); 2196 } 2197 setring R; 2198 poly fNew = imap(Q, fNew); 2199 } else 2200 { 2201 setring R; 2202 poly fNew = (var(2) - f)^d; 2203 } 2204 return(fNew); 2205 } 2206 2207 //////////////////////////////////////////////////////////////////////// 2208 2209 // Product of conjugate factors 2210 // Input: a polynomial f over an algebraic extension of the base ring. 2211 // Output: polynomial = the product of (y-f_i) for all conjugate polynomials 2212 // f_i of f. 2213 static proc buildPolyFrac(poly f) 2214 { 2215 int i; 2216 def R = basering; 2217 2218 intvec dx = (1,0); 2219 int degX = deg(f, dx); 2220 2221 poly mp = minpoly; 2222 2223 2224 mp = subst(minpoly, @a, var(1)); 2225 int d = pardeg(minpoly); 2226 def Q = ring(0, (var(1), var(2), @a, T(1..d)), lp); 2227 ring S = 0, (var(1), @a), dp; 2228 poly f = imap(R, f); 2229 intvec da = (0,1); 2230 2231 if(deg(f, da) > 0) 2232 { 2233 poly mp = imap(R, mp); 2234 mp = subst(mp,var(1),@a); 2235 setring Q; 2236 poly f = imap(S, f); 2237 poly mp = imap(S, mp); 2238 mp = mp / leadcoef(mp); 2239 poly fNew = 1; 2240 poly rels = 1; 2241 //ideal I = var(1)^(degX + 1); // We use this to reduce modulo x^maxDeg 2242 ideal I; // We use this to reduce modulo x^maxDeg 2243 for(i = 1; i <= d; i++) 2244 { 2245 rels = rels * (var(1) - T(i)); 2246 } 2247 matrix c1 = coeffs(rels, var(1)); 2248 matrix c2 = coeffs(mp, @a); 2249 for(i = 1; i<=d; i++) 2250 { 2251 I[i] = c1[i,1] - c2[i,1]; 2252 } 2253 I = groebner(I); 2254 2255 int t = timer; 2256 poly fTemp; 2257 for(i = 1; i<=d; i++) 2258 { 2259 fTemp = subst(f, @a, T(i)); 2260 fNew = fNew * (var(2) - fTemp); 2261 fNew = reduce(fNew, I); 2262 } 2263 debug_log_intbas(4,"--------Time for product reduction: ", timer - t); 2264 2265 setring R; 2266 poly fNew = imap(Q, fNew); 2267 2268 } else 2269 { 2270 setring R; 2271 poly fNew = (var(2) - f)^d; 2272 } 2273 return(fNew); 2274 } 2275 2276 //////////////////////////////////////////////////////////////////////// 2277 2278 // Polynomail over the ground field. 2279 // Input: a list of polynomials representing Puiseux expansions and 2280 // an integer sD representing the denominator of the exponents in 2281 // all the expansions. 2282 // Output: polynomial = the product of all the expansions in the input list. 2283 // The common denominator is now cancelled with the numerators. 2284 static proc buildPolyGround(list fFrac, int sD) 2285 { 2286 int i; 2287 int gfCheck = 1; // The polynomial computed is over the ground field. 2288 // This means the conjugacy is computed correctly. 2289 def R = basering; 2290 poly f = 1; 2291 intvec vx = (1, 0); 2292 for(i = 1; i <= size(fFrac); i++) 2293 { 2294 f = f * fFrac[i]; 2295 } 2296 ring P = (0, @a), (@x, @y, @X), dp; 2297 poly fNew = fetch(R, f); 2298 poly f2 = reduce(fNew, groebner(@X-@x^sD)); 2299 if(deg(f2, (1,0,0)) > 0) 2300 { 2301 "f2", f2; 2302 "Polynomial is not over the ground field"; 2303 ~; 2304 gfCheck = 0; 2305 } 2306 f2 = subst(f2, @X, @x); 2307 setring R; 2308 poly fNew = fetch(P, f2); 2309 return(list(fNew, gfCheck)); 2310 } 2311 2312 //////////////////////////////////////////////////////////////////////// 2313 2314 // Valuations of products of expansions with respect to expansions of the 2315 // same class. 2316 // Input: a list bF of lists of polynomials, as given by proc buildFactors. 2317 // an intvec md representing the degrees of the minimal polynomials 2318 // of the extension used for each expansion. 2319 // Output: two lists. The i-th element of the first list is a list of 2320 // numbers, representing the valutations of taking 1 to d-1 expansions 2321 // in the i-th conjugacy class given in bF, with respect to an 2322 // expansion of that same class 2323 // [Example 1] 2324 static proc valIKSelf(list bF, intvec md) 2325 { 2326 int i, k; 2327 list facs = bF[1]; 2328 list ords = bF[2]; // The order of the factors 2329 list degs = bF[3]; // The degree of the factors in y 2330 int b = size(ords); // Number of blocks 2331 list MSelf; 2332 list bestElem; 2333 number o; 2334 int d, dT; 2335 poly p; 2336 for(i = 1; i <= b; i++) 2337 { 2338 MSelf[i] = list(); 2339 bestElem[i] = list(); 2340 for(d = 1; d < md[i]; d++) 2341 { 2342 o = d * number(ords[i][1]); 2343 for(k = 2; k <= size(degs[i]); k++) 2344 { 2345 o = o + number(int(d div degs[i][k])) * (number(ords[i][k]) - number(ords[i][k-1])); 2346 } 2347 MSelf[i][d] = o; 2348 2349 p = 1; 2350 // fa[3] are the degrees of the polynomials 2351 dT = d; 2352 for(k = size(degs[i]); k >= 1; k--) 2353 { 2354 p = p * facs[i][k]^(int(dT div degs[i][k])); 2355 dT = dT mod degs[i][k]; 2356 } 2357 bestElem[i][d] = p; 2358 } 2359 } 2360 2361 return(list(MSelf, bestElem)); 2362 } 2363 2364 //////////////////////////////////////////////////////////////////////// 2365 2366 // Valuations of differences of non-conjugate expansions. 2367 // Input: a list classes of classes of conjugate expansions, as given by 2368 // proc getClasses 2369 // Output: a matrix M of number, where M[i, j] is the valuation 2370 // of gamma_i - gamma_j, expansions of the i-th and j-th conjugacy 2371 // class respectively. 2372 static proc valIK(list classes) 2373 { 2374 int i, j; 2375 def R = basering; 2376 matrix M[size(classes)][size(classes)]; 2377 for(i = 1; i <= size(classes); i++) 2378 { 2379 if(typeof(classes[i][1]) == "ring") 2380 { 2381 def S = classes[i][1]; 2382 setring S; 2383 poly f = subst(PE[1][1], @a, 0); 2384 int den(i) = PE[1][2]; 2385 number o = number(ratDeg(PE[1][1])) / number(den(i)); 2386 setring R; 2387 poly f(i) = imap(S, f); 2388 number o(i) = number(imap(S, o)); 2389 int nonRat(i) = 1; 2390 setring S; 2391 kill f; 2392 kill o; 2393 setring R; 2394 kill S; 2395 } else 2396 { 2397 poly f(i) = classes[i][1][1]; 2398 int den(i) = classes[i][1][2]; 2399 number o(i) = number(orderExp(f(i))) / number(den(i)); 2400 int nonRat(i) = 0; 2401 } 2402 } 2403 2404 int k; 2405 poly differ; 2406 number ordDiff; 2407 for(i = 1; i <= size(classes); i++) 2408 { 2409 M[i, i] = o(i); 2410 for(j = 1; j < i; j++) 2411 { 2412 differ = subst(f(i), var(1), var(1)^den(j)) - subst(f(j), var(1), var(1)^den(i)); 2413 if(differ != 0){ 2414 k = orderExp(differ); 2415 ordDiff = number(k) / number(den(i)*den(j)); 2416 // The order of the difference cannot be greater than the o(i) when 2417 // the i-th expansion is non-rational when all the expansions in the 2418 // block are in the same class. 2419 if((nonRat(i) == 1) and (ordDiff > o(i))) 2420 { 2421 ordDiff = o(i); 2422 } 2423 if((nonRat(j) == 1) and (ordDiff > o(j))) 2424 { 2425 ordDiff = o(j); 2426 } 2427 M[i, j] = ordDiff; 2428 M[j, i] = ordDiff; 2429 } else 2430 { 2431 M[i, j] = o(i); 2432 if(o(j) < o(i)) 2433 { 2434 M[i, j] = o(j); 2435 } 2436 M[j, i] = M[i, j]; 2437 } 2438 } 2439 } 2440 return(M); 2441 } 2442 2443 //////////////////////////////////////////////////////////////////////// 2444 2445 // Input: a polynomial f. 2446 // Output: an integer k = the order of f (that is, the smallest exponent of f 2447 // as poly in the first variable). 2448 static proc orderExp(poly f){ 2449 if(f == 0) 2450 { 2451 return(-1); 2452 } else 2453 { 2454 matrix co = coeffs(f, var(1)); 2455 int k = 1; 2456 while(co[k, 1] == 0){ 2457 k++; 2458 } 2459 k--; 2460 } 2461 return(k); 2462 } 2463 2464 // Input: a list l of puiseux expansions 2465 // Output: a set of polynomials = the rational part of each expansion in l 2466 //static proc truncPoly(list l) 2467 //{ 2468 // int i, j; 2469 // def R = basering; 2470 // ring P = 0, (x,y,X), dp; 2471 // poly fNew; 2472 // poly f2; 2473 // setring R; 2474 // 2475 // for(i = 1; i <= size(l); i++) 2476 // { 2477 // if(typeof(l[i]) == "ring") 2478 // { 2479 // def S = l[i]; 2480 // setring S; 2481 // poly f = subst(PE[1][1], @a, 0); 2482 // int den(i) = PE[1][2]; 2483 // setring R; 2484 // poly f(i) = imap(S, f); 2485 // setring S; 2486 // kill f; 2487 // setring R; 2488 // kill S; 2489 // } else { 2490 // poly f(i) = l[i][1]; 2491 // int den(i) = l[i][2]; 2492 // } 2493 // setring P; 2494 // fNew = fetch(R, f(i)); 2495 // f2 = reduce(fNew, groebner(X - x^den(i))); 2496 // f2 = subst(f2, X, x); 2497 // setring R; 2498 // f(i) = var(2) - fetch(P, f2); 2499 // } 2500 // return(f(1..size(l))); 2501 //} 2502 2503 //////////////////////////////////////////////////////////////////////// 2504 2505 // Input: matrix M of valuations of differences of expansions of different 2506 // classes, list MSelf of valuations of an expansions with respect 2507 // to valuations of the same class, integer d the degree of the 2508 // required element, intvec md = the number of expansions in each 2509 // class. 2510 // Output: the maximal valuation of an element of degree d, and the 2511 // corresponding element. 2512 static proc ibElement(matrix M, list MSelf, int d, intvec md) 2513 { 2514 // Best i 2515 int i, j, k; 2516 int top = d; 2517 int s = ncols(M); 2518 2519 intvec vy = (0,1); 2520 intvec vx = (1,0); 2521 number order(1..s); 2522 number minOrd; 2523 number maxExp = 0; 2524 int maxExpi; // The value of i for the max exp. 2525 2526 list sums = summands(d, s, md); 2527 2528 for(i = 1; i <= size(sums); i++) 2529 { 2530 minOrd = 0; 2531 for(j = 1; j <= s; j++) 2532 { 2533 order(j) = 0; 2534 for(k = 1; k <= s; k++) 2535 { 2536 if(order(j) > -1) 2537 { 2538 if(k != j) 2539 { 2540 order(j) = order(j) + number(sums[i][k]) * number(M[k, j]); 2541 } else 2542 { 2543 if (sums[i][k] < md[j]) 2544 { 2545 if(sums[i][k] > 0) 2546 { 2547 order(j) = order(j) + MSelf[j][sums[i][k]]; 2548 } 2549 } else 2550 { 2551 order(j) = -1; 2552 } 2553 } 2554 } 2555 } 2556 if(((order(j) < minOrd) or (minOrd == 0)) and (order(j) > -1)) 2557 { 2558 minOrd = order(j); 2559 } 2560 } 2561 if(minOrd > maxExp) 2562 { 2563 maxExp = minOrd; 2564 maxExpi = i; 2565 } 2566 } 2567 intvec elem = sums[maxExpi]; 2568 return(list(maxExp, elem)); 2569 } 2570 2571 //////////////////////////////////////////////////////////////////////// 2572 2573 // Input: int n, int k, intvec md of size k 2574 // Output: matrix such that it each row is a way of expressing n 2575 // as a sum of k non-negative integers, where the i-th integer is 2576 // smaller or equal than md[i]. 2577 static proc summands(int n, int k, intvec md) 2578 { 2579 list l; 2580 list lT; 2581 intvec v; 2582 int i, j; 2583 int m; 2584 intvec mdT; 2585 if(k > 1){ 2586 m = md[1]; 2587 if(m > n) 2588 { 2589 m = n; 2590 } 2591 for(i = m; i>= 0; i = i-1) 2592 { 2593 mdT = md[2..k]; 2594 lT = summands(n-i, k-1, mdT); 2595 for(j = 1; j <= size(lT); j++) 2596 { 2597 v = i, lT[j]; 2598 l = insert(l, v); 2599 } 2600 } 2601 } else { 2602 if(n <= md[1]) 2603 { 2604 l = insert(l, n); 2605 } 2606 } 2607 return(l); 2608 } 2609 2610 // Input: int n, int k, intvec md of size k 2611 // Output: matrix such that it each row is a way of expressing n 2612 // as a sum of k non-negative integers, where the i-th integer is 2613 // smaller or equal than md[i]. 2614 static proc summandAll(intvec md) 2615 { 2616 int k = size(md); 2617 list l; 2618 list lT; 2619 intvec v; 2620 int i, j; 2621 int m; 2622 intvec mdT; 2623 if(k > 1){ 2624 m = md[1]; 2625 for(i = 0; i <= m; i = i + 1) 2626 { 2627 mdT = md[2..k]; 2628 lT = summandAll(mdT); 2629 for(j = 1; j <= size(lT); j++) 2630 { 2631 v = i, lT[j]; 2632 l = l + list(v); 2633 } 2634 } 2635 } else { 2636 for(i = 0; i <= md[1]; i = i+1) 2637 { 2638 l = l + list(i); 2639 } 2640 } 2641 return(l); 2642 } 2643 2644 2645 // Next element in a list of integers 2646 static proc nextSummand(intvec md, intvec ch, int cl) 2647 { 2648 int k = nrows(md); 2649 int pos = 1; 2650 if(cl == pos){pos = pos + 1;} 2651 ch[pos] = ch[pos] + 1; 2652 2653 // "md: ", md; 2654 // "ch: ", ch; 2655 // "cl: ", cl; 2656 while(ch[pos] > md[pos]) 2657 { 2658 ch[pos] = 0; 2659 pos = pos + 1; 2660 ch[pos] = ch[pos] + 1; 2661 } 2662 // "output: ", ch; 2663 return(ch); 2664 } 2665 2666 //////////////////////////////////////////////////////////////////////// 2667 2668 // Input: poly f in L[x], with L an algebraic extension of K. 2669 // Output: int k = the degree of the first term whose coefficient is in L - K 2670 static proc ratDeg(poly f) 2671 { 2672 matrix c = coeffs(f, var(1)); 2673 int k = 1; 2674 while((pardeg(number(c[k,1])) <= 0) and (k < size(c))) 2675 { 2676 k++; 2677 } 2678 if(pardeg(number(c[k,1])) > 0) 2679 { 2680 k--; 2681 } 2682 return(k); 2683 } 2684 2685 // Input: a list classes, whose elements are classes of conjugate Puiseux 2686 // expansions, as returned by proc getClasses. 2687 // Output: a list of intvec, where the first element of each vector is the 2688 // numerator and the second one the denominator of the (rational) 2689 // order of the Puiseux expansions in each class. 2690 static proc getSlopes(list classes) 2691 { 2692 int i; 2693 list slopes; 2694 2695 def R = basering; 2696 2697 for(i = 1; i <= size(classes); i++) 2698 { 2699 if(typeof(classes[i][1]) == "ring") 2700 { 2701 def S = classes[i][1]; 2702 setring S; 2703 slopes[i] = intvec(orderExp(PE[1][1]), PE[1][2]); 2704 setring R; 2705 kill S; 2706 } else 2707 { 2708 slopes[i] = intvec(orderExp(classes[i][1][1]), classes[i][1][2]); 2709 } 2710 } 2711 return(slopes); 2712 } 2713 2714 //////////////////////////////////////////////////////////////////////// 2715 2716 // Input: a list l of rings, each of these rings containing a list PE of 2717 // Puiseux expansions. 2718 // Output: a list of rings, with one ring for each of the Puiseux expansions 2719 // in the original rings. 2720 static proc explodeRings(list l) 2721 { 2722 def R = basering; 2723 2724 int i, j; 2725 int numb; 2726 list rings; 2727 2728 for(i = 1; i <= size(l); i++){ 2729 if(typeof(l[i]) == "ring"){ 2730 def S = l[i]; 2731 setring S; 2732 list rl; 2733 numb = size(PE); 2734 for(j = 1; j <= numb; j++){ 2735 rl = ringlist(S); 2736 def SS = ring(rl); 2737 setring SS; 2738 list PET = fetch(S, PE); 2739 list PE = list(PET[j]); 2740 list erg = fetch(S, erg); 2741 list minPolys = fetch(S, minPolys); 2742 export(PE); 2743 export(erg); 2744 export(minPolys); 2745 kill PET; 2746 setring R; 2747 rings = rings + list(SS); 2748 setring S; 2749 kill SS; 2750 } 2751 } 2752 } 2753 setring R; 2754 return(rings); 2755 } 2756 2757 // Input: a list l, whose elements are either Puiseux expansions over the 2758 // base ring or rings containing a list PE of Puiseux expansions. 2759 // Output: a list classes, where each element is a list of conjugate 2760 // Puiseux expansions (given also either as expansions over the base 2761 // rings or defined in extension rings). 2762 static proc getClasses(list l) 2763 { 2764 int i; 2765 int j; 2766 int cc; 2767 int prevI; 2768 list code; 2769 list classCode; 2770 list classes; 2771 2772 list l2; 2773 for(i = 1; i <= size(l); i++) 2774 { 2775 if(typeof(l[i]) == "ring"){ 2776 l2 = l2 + explodeRings(l[i]); 2777 } else 2778 { 2779 l2 = l2 + list(l[i]); 2780 } 2781 } 2782 l = l2; 2783 2784 int k = 1; 2785 classes[k] = list(); 2786 classes[k][1] = l[1]; 2787 classCode[1] = 1; 2788 2789 def R = basering; 2790 2791 for(i = 1; i <= size(l); i++){ 2792 if(typeof(l[i]) == "ring"){ 2793 def S = l[i]; 2794 setring S; 2795 code[i] = PE[1][6]; 2796 setring R; 2797 kill S; 2798 } else { 2799 code[i] = l[i][6]; 2800 } 2801 if(i>1) 2802 { 2803 prevI = 0; 2804 for(j = 1; j < i; j++) 2805 { 2806 if(equalLists(code[i], code[j])) 2807 { 2808 prevI = j; 2809 } 2810 } 2811 if(prevI == 0) 2812 { 2813 k++; 2814 classes[k] = list(); 2815 classes[k][1] = l[i]; 2816 classCode[i] = k; 2817 } else 2818 { 2819 cc = classCode[prevI]; 2820 classes[cc][size(classes[cc])+1] = l[i]; 2821 classCode[i] = classCode[prevI]; 2822 } 2823 } 2824 } 2825 return(classes); 2826 } 2827 2828 //////////////////////////////////////////////////////////////////////// 2829 2830 // Input: a list classes, whose elements are classes of conjugate Puiseux 2831 // expansions, as returned by proc getClasses. 2832 // Output: an intvec degs, where the i-th element is the number of Puiseux 2833 // expansions in the i-th class (which is equal to the degree in y 2834 // of the factor corresponding to that conjugacy class). 2835 static proc getDegs(list classes) 2836 { 2837 int i, j; 2838 intvec degs; 2839 2840 def R = basering; 2841 int degBase = 1; 2842 if(pardeg(minpoly) != -1) 2843 { 2844 degBase = pardeg(minpoly); 2845 } 2846 2847 for(i = 1; i <= size(classes); i++) 2848 { 2849 degs[i] = 0; 2850 for(j = 1; j <= size(classes[i]); j++) 2851 { 2852 if(typeof(classes[i][j]) == "ring") 2853 { 2854 def S = classes[i][j]; 2855 setring S; 2856 degs[i] = degs[i] + (pardeg(minpoly) div degBase)*size(PE); 2857 setring R; 2858 kill S; 2859 } else 2860 { 2861 degs[i] = degs[i] + 1; 2862 } 2863 } 2864 } 2865 return(degs); 2866 } 2867 2868 //////////////////////////////////////////////////////////////////////// 2869 2870 // Input: a list l, whose elements are either Puiseux expansions over the 2871 // base ring or rings containing a list PE of Puiseux expansions. 2872 // Output: an integer d = sum of the degrees of the singular part of all the 2873 // Puiseux expansions in the input. 2874 static proc getTotalDeg(list l) 2875 { 2876 int i, j; 2877 number d = 0; 2878 number d2; 2879 int dT, nT; 2880 int mT; 2881 def R = basering; 2882 for(i = 1; i <= size(l); i++) 2883 { 2884 if(typeof(l[i]) == "ring") 2885 { 2886 def SS = l[i]; 2887 setring SS; 2888 number dTemp; 2889 dTemp = 0; 2890 mT = pardeg(minpoly); 2891 for(j = 1; j <= size(PE); j++) 2892 { 2893 nT = deg(PE[j][1]); 2894 dT = PE[j][2]; 2895 dTemp = dTemp + (number(nT) / dT) * mT; 2896 } 2897 setring R; 2898 d2 = number(imap(SS, dTemp)); 2899 d = d + d2; 2900 kill SS; 2901 } else 2902 { 2903 d = d + number(deg(l[i][1])) / l[i][2]; 2904 } 2905 } 2906 if(d == int(d)) 2907 { 2908 return(int(d)); 2909 } else 2910 { 2911 //"Computing Puiseux expansions over an algebraic extension! Please check correct output..."; 2912 //"Input: list l"; 2913 //l; 2914 //"Output: int d"; 2915 //int(d) + 1; 2916 return(int(d) + 1); 2917 } 2918 } 2919 2920 //////////////////////////////////////////////////////////////////////// 2921 2922 // Product modulo x^e. 2923 // Input: poly p, q in k[x][y], int expo 2924 // Output: p * q reduced mod x^e. 2925 // Remarks: it is assumed that x is the first variable in the ring. 2926 static proc prodMod(poly p, poly q, int expo) 2927 { 2928 def R = basering; 2929 qring Q = var(1)^expo; 2930 poly p = imap(R, p); 2931 poly q = imap(R, q); 2932 poly pq = p*q; 2933 setring R; 2934 poly pq = imap(Q, pq); 2935 pq = reduce(pq, groebner(var(1)^expo)); 2936 return(pq); 2937 } 2938 2939 //////////////////////////////////////////////////////////////////////// 2940 2941 // Computed the order of poly h at the expansion defined by S, 2942 // which may be a ring or a Puiseux expansion 2943 static proc ordAtPol(poly h, def S) 2944 { 2945 def R = basering; 2946 2947 if(typeof(S) == "ring") 2948 { 2949 setring S; 2950 poly h = imap(R, h); 2951 poly g = PE[1][1]; 2952 int den = PE[1][2]; 2953 2954 //"here"; 2955 //"h, g", h, g; 2956 2957 //"b debug overflow <-"; 2958 2959 if(size(h) > 1) 2960 { 2961 h = subst(h, var(1), var(1)^den); 2962 poly hs = subst(h, var(2), g); 2963 //"b debug overflow <-"; 2964 2965 matrix MM; 2966 MM = coef(hs, var(1)); 2967 int oo = deg(MM[1, ncols(MM)]); 2968 kill hs; 2969 } else 2970 { 2971 matrix MM; 2972 MM = coef(g, var(1)); 2973 int oo = deg(MM[1, ncols(MM)])*deg(h, intvec(0,1)) + deg(h, intvec(1,0))*den; 2974 } 2975 //~; 2976 2977 number oro = oo/number(den); 2978 2979 //"h, oro", h, oro; 2980 kill h; 2981 kill g; 2982 kill MM; 2983 setring R; 2984 number oro2 = number(imap(S, oro)); 2985 setring S; 2986 kill oro; 2987 setring R; 2988 } else 2989 { 2990 int den = S[2]; 2991 poly g = S[1]; 2992 h = subst(h, var(1), var(1)^den); 2993 poly hs = subst(h, var(2), g); 2994 2995 matrix MM; 2996 MM = coef(hs, var(1)); 2997 int oo = deg(MM[1, ncols(MM)]); 2998 2999 number oro2 = oo/number(den); 3000 } 3001 return(oro2); 3002 } 3003 3004 //////////////////////////////////////////////////////////////////////// 3005 3006 // Computes the factors of f corresponding to each conjugacy class, 3007 // up to degree degExpand 3008 static proc irreducibleFactors(poly f, list classes, int degExpand) 3009 { 3010 list I2Lifted = henselBlocks(f, degExpand, 1); 3011 3012 int nClasses; 3013 nClasses = size(classes); 3014 3015 int gfCheck = 1; // For checking if the polynomial is over 3016 // the ground field. 3017 list gfCheckList; 3018 3019 //"nClasses: ", nClasses; 3020 //"size(I2Lifted): ", size(I2Lifted); 3021 //"I2Lifted: ", I2Lifted; 3022 //"degExpand: ", degExpand; 3023 3024 int wrongNumber = 0; // If some hensel block contains different classes 3025 3026 // CHECK THIS. How to count factor outside the origin? 3027 if(nClasses != (size(I2Lifted) - 1)) 3028 { 3029 3030 list newL; 3031 list I2LiftedNew; 3032 I2LiftedNew[1] = I2Lifted[1]; 3033 int ind = 2; 3034 list classes2; 3035 poly fu, fuProd; 3036 list fuPols; 3037 int PEPE; 3038 int cl; 3039 int i, j; 3040 3041 list bPG; 3042 3043 def R = basering; 3044 3045 for(i = 2; i <= size(I2Lifted); i++) 3046 { 3047 //"Computing singular part of Puiseux expansions of factor ", i, ": ", I2Lifted[i]; 3048 newL = puiseux(I2Lifted[i], -1, 1); 3049 classes2 = getClasses(newL); 3050 3051 3052 if(size(classes2) > 1) 3053 { 3054 // We recompute up to the appropiate order for merging 3055 poly I2Red = reduce(I2Lifted[i], var(1)^(degExpand+1)); 3056 3057 //"Computing Puiseux expansions up to degree degExpand of factor ", i, ": ", I2Red; 3058 3059 newL = puiseux(I2Red, degExpand, 1); 3060 classes2 = getClasses(newL); 3061 3062 for(j = 1; j <= size(classes2); j++) 3063 { 3064 fuProd = 1; 3065 fuPols = list(); 3066 // FIX THIS FOR PUISEUX EXPANSIONS THAT ARE NOT GIVEN AS RINGS 3067 // Check example 3068 // ring R = 0, (X,Y), dp; 3069 // poly f = (Y^6-6*X^3*Y^4-2*X^7*Y^3+12*X^6*Y^2-12*X^10*Y-8*X^9)*(Y^2-2*Y*X^3-2*X^3)*(Y^2+X^7)+X^30; 3070 // list l = integralBasis(f,2,"atOrigin"); 3071 3072 3073 for(cl = 1; cl <= size(classes2[j]); cl++) 3074 { 3075 3076 if(typeof(classes2[j][cl]) == "ring") 3077 { 3078 def S = classes2[j][cl]; 3079 setring S; 3080 3081 poly fu = buildPolyFrac(PE[1][1]); 3082 3083 PEPE = PE[1][2]; 3084 3085 setring R; 3086 fu = imap(S, fu); 3087 kill S; 3088 fuProd = fuProd * fu; 3089 } else 3090 { 3091 "RING EXPECTED! Please contact the developers."; 3092 ~; 3093 } 3094 } 3095 3096 bPG = buildPolyGround(fuProd, PEPE); 3097 3098 if(bPG[2] == 0) 3099 { 3100 // The polynomial computed is not over the ground field. 3101 // The classes computed are wrong, we need to recompute. 3102 "Polynomial not over the ground field."; 3103 gfCheck = 0; 3104 } 3105 3106 fu = reduce(bPG[1], groebner(var(1)^degExpand)); 3107 3108 I2LiftedNew[ind] = fu; 3109 gfCheckList[ind] = bPG[2]; 3110 3111 ind = ind + 1; 3112 } 3113 } else { 3114 I2LiftedNew[ind] = I2Lifted[i]; 3115 ind = ind + 1; 3116 } 3117 } 3118 I2Lifted = I2LiftedNew; 3119 wrongNumber = 1; 3120 } 3121 list ll = list(I2Lifted, gfCheckList, gfCheck, wrongNumber); 3122 3123 return(ll); 3124 } 3125 3126 //////////////////////////////////////////////////////////////////////// 3127 // Computes the maximum degree needed of the factors 3128 3129 // Input: n is the degree of f 3130 // cl is the index of the class for which the loc basis is computed. 3131 // Output: maximal degree needed for computing the basis 3132 // [Example 4] 3133 3134 static proc maxDegMerge(int n, int cl, int locBasis, int d0, matrix M, list MSelf, intvec md, list classes, list I2Lifted, list bestElem, matrix ordsFull, list ordsBest); 3135 { 3136 //"START - newib.lib - maxDegMerge - 4"; 3137 int tt = timer; 3138 def R = basering; 3139 3140 int i, j, k; 3141 list ibNum, ibDen; 3142 number expUnit; // The integrality exponent of the local unit 3143 poly polyUnit; 3144 3145 intvec vy = (0,1); 3146 intvec vx = (1,0); 3147 3148 poly baseFactor; 3149 number expBaseFactor; 3150 poly locLocFactor = 1; 3151 expUnit = 0; 3152 3153 def SS = classes[cl][1]; 3154 3155 // This corrects for some wrongly computed number of classes 3156 int nClasses; 3157 // if(size(classes) > size(I2Lifted) - 1) 3158 // { 3159 // nClasses = size(I2Lifted) - 1; 3160 // } else 3161 // { 3162 // nClasses = size(classes); 3163 // } 3164 nClasses = size(classes); 3165 3166 3167 if(nClasses > 1) 3168 { 3169 for(j = 1; j <= size(I2Lifted)-1; j++) 3170 { 3171 if(j != cl) 3172 { 3173 expUnit = expUnit + number(ordsFull[j, cl]); 3174 } 3175 } 3176 // The first term containing the locloc unit 3177 expBaseFactor = expUnit; 3178 3179 // If the order of hi is not integer, we add a factor. 3180 if(int(denominator(expBaseFactor)) > 1) 3181 { 3182 3183 // We add the factor corresponding to the full expansions 3184 list fullPoly; 3185 for(j = 1; j <= nClasses; j++) 3186 { 3187 fullPoly[j] = I2Lifted[j+1]; 3188 } 3189 3190 int whichElem = 0; 3191 int den1; 3192 int den2; 3193 3194 intvec degsCl; 3195 for(i = 1; i <= size(MSelf); i++) 3196 { 3197 degsCl[i] = size(MSelf[i]) + 1; 3198 } 3199 intvec chVec = 0:size(MSelf); 3200 3201 den1 = 1; 3202 den2 = int(denominator(expBaseFactor)); 3203 3204 number ordNewFactor; 3205 3206 number oAP; 3207 number oAPT; 3208 3209 while(den1 mod den2 != 0) 3210 { 3211 chVec = nextSummand(degsCl, chVec, cl); 3212 ordNewFactor = 0; 3213 for(i = 1; i <= nClasses; i++) 3214 { 3215 if(i != cl) 3216 { 3217 k = chVec[i]; 3218 //"i, k", i, k; 3219 if(k > 0) 3220 { 3221 if(k <= size(bestElem[i])) 3222 { 3223 oAP = ordsBest[cl][i][k]; 3224 ordNewFactor = ordNewFactor + oAP; 3225 } else 3226 { 3227 oAP = number(ordsFull[i, cl]); 3228 ordNewFactor = ordNewFactor + oAP; 3229 } 3230 } 3231 } 3232 } 3233 den1 = int(denominator(ordNewFactor)); 3234 } 3235 3236 poly newFactor = 1; 3237 int denNewFactor = den1; 3238 int powFactor = 0; 3239 3240 int nnE = int(numerator(expBaseFactor)); 3241 int ddE = int(denominator(expBaseFactor)); 3242 int nnY = int(numerator(ordNewFactor)); 3243 3244 while(ddE > 1) 3245 { 3246 powFactor = powFactor + 1; 3247 expBaseFactor = expUnit + powFactor * ordNewFactor; 3248 ddE = int(denominator(expBaseFactor)); 3249 } 3250 } 3251 } else 3252 { 3253 expBaseFactor = 0; 3254 } 3255 3256 int eu; 3257 number euNum; 3258 3259 euNum = expBaseFactor; 3260 if(size(MSelf[cl]) > 0) 3261 { 3262 euNum = expBaseFactor + MSelf[cl][md[cl]-1]; 3263 } 3264 eu = int(euNum); 3265 debug_log_intbas(3, "------Time maxDegMerge: ", timer - tt); 3266 3267 return(eu); 3268 } 3269 3270 //////////////////////////////////////////////////////////////////////// 3271 3272 // Computes the order of a polynomial h at the classes from list classes 3273 // indicated by an entry 1 in the vector classesInd 3274 static proc ordAtClassesPol(poly h, list classes, intvec classesInd) 3275 { 3276 int i, j; 3277 number expUnit = 0; 3278 number expUnitTemp; 3279 3280 for(i = 1; i <= size(classes); i++) 3281 { 3282 if(classesInd[i] == 1) 3283 { 3284 expUnitTemp = ordAtPol(h, classes[i][1]); 3285 if((expUnit == 0) || (expUnitTemp < expUnit)) 3286 { 3287 expUnit = expUnitTemp; 3288 } 3289 } 3290 } 3291 return(expUnit); 3292 } 3293 3294 //////////////////////////////////////////////////////////////////////// 3295 3296 // Computes the order of a product of polynomials at a list of classes 3297 static proc ordAtClasses(list classes, list fullPoly, intvec classes1Ind, intvec classes2Ind) 3298 { 3299 int i, j; 3300 number expUnit = 0; 3301 number expUnitTemp; 3302 3303 for(i = 1; i <= size(classes); i++) 3304 { 3305 if(classes1Ind[i] == 1) 3306 { 3307 expUnitTemp = 0; 3308 for(j = 1; j <= size(classes); j++) 3309 { 3310 if(classes2Ind[j] == 1) 3311 { 3312 expUnitTemp = expUnitTemp + ordAtPol(fullPoly[j], classes[i][1]); 3313 } 3314 } 3315 if((expUnit == 0) || (expUnitTemp < expUnit)) 3316 { 3317 expUnit = expUnitTemp; 3318 } 3319 } 3320 } 3321 return(expUnit); 3322 } 3323 3324 //////////////////////////////////////////////////////////////////////// 3325 3326 // Takes the common denominator in a list of polynomial fractions 3327 static proc comDen(list ibNum, list ibDen) 3328 { 3329 int i; 3330 ideal IOut; 3331 poly ibComDen = 1; 3332 3333 for(i = 1; i <= size(ibNum); i++) 3334 { 3335 ibComDen = lcm(ibComDen, ibDen[i]); 3336 } 3337 3338 // Common denominator 3339 for(i = 1; i <= size(ibNum); i++) 3340 { 3341 IOut[i] = (ibNum[i] * ibComDen) / ibDen[i]; 3342 } 3343 3344 list out = IOut, ibComDen; 3345 return(out); 3346 } 3347 3348 3349 ///////////////////////////////////////////////////////////////////////////// 3350 // 3351 // Auxiliar tools 3352 // 3353 ///////////////////////////////////////////////////////////////////////////// 3354 3355 // The maximum between a and b 3356 static proc maxInt(int a, int b) 3357 { 3358 if(a > b) 3359 { 3360 return(a); 3361 } else { 3362 return(b); 3363 } 3364 } 3365 3366 // Computes a polynomial over the ground field that together with the 3367 // elements of slower degree in the IB, generates the same ring as the 3368 // polynomial in the extension field. 3369 // Remark: it is assumed that x is the first variable. 3370 static proc elimPar(list ib, int i) 3371 { 3372 // Trivial case 3373 if(i == 1) 3374 { 3375 //"Trivial case"; 3376 return(ib[1][1]); 3377 } 3378 3379 int t = timer; 3380 int j; 3381 def BR = basering; 3382 poly pa = subst(minpoly, @a, var(1)); 3383 3384 // We use a lexicographical ordering so that the parameter is eliminated. 3385 ring ER = 0, (@a,var(1),var(2)), lp; 3386 intvec va = (1,0,0); 3387 3388 // pa will be a polynomial in a. 3389 poly pa = fetch(BR, pa); 3390 3391 // remi will be the ideal of the generators of smaller degree, after taking 3392 // common denominator. 3393 ideal remi; 3394 list ib = imap(BR, ib); 3395 3396 int mExp = ib[i][2]; 3397 if(mExp > ib[i][2]) 3398 { 3399 "WRONG EXPONENT. CHECK!!"; 3400 ~; 3401 setring BR; 3402 return(var(2) * ib[i-1][1]); 3403 } 3404 3405 for(j = 1; j < i; j++) 3406 { 3407 // var(2) is now x 3408 remi[j] = ib[j][1] * (var(2)-@a)^(mExp - ib[j][2]); 3409 } 3410 3411 // Module reduction - NOT WORKING!! TO DO!! 3412 //"Module reduction"; 3413 //"remi: "; remi; 3414 //"pa: ", pa; 3415 //"ib[i][1]: ", ib[i][1]; 3416 //poly redT = moduleReduction(remi, pa, ib[i][1]); 3417 3418 remi[i] = pa; 3419 remi = groebner(remi); 3420 3421 // We reduce the last element by the rest of the elements 3422 poly red = reduce(ib[i][1], remi); 3423 3424 if(deg(red, va) > 0) 3425 { 3426 "Wrong degree! Check!"; 3427 ~; 3428 } 3429 setring BR; 3430 poly red = imap(ER, red); 3431 return(red); 3432 } 3433 3434 // The number of different initial coefficients must be equal to the 3435 // order b of the singular points. 3436 static proc newtonInfo(poly f, int b){ 3437 //"START - ibasis.lib - newtonInfo"; 3438 int i; 3439 int slN, slD; 3440 int g; 3441 int dbg = printlevel - voice + 4; 3442 3443 list l = newtonpoly(f); 3444 if(size(l) > 2){ 3445 dbprint(dbg, "The Puiseux Expansions have different initial exponents. New algorithm not implemented for this case."); 3446 return(list()); 3447 } else { 3448 slN = l[2][1] - l[1][1]; 3449 slD = l[1][2] - l[2][2]; 3450 g = gcd(slD, slN); 3451 slD = slD div g; 3452 slN = slN div g; 3453 poly pp = Puiseuxexpansions::puiseuxStep(f, slN, slD); 3454 if(deg(pp) < b){ 3455 dbprint(dbg, "The Puiseux Expansions have repeated initial coefficients. New algorithm not implemented for this case."); 3456 return(list()); 3457 } 3458 poly sqpp = squarefree(pp); 3459 // CHECK! Case deg sqpp = 1 might not be fully implemented. 3460 if((deg(sqpp) > 1) and (deg(sqpp) < deg(pp))){ 3461 dbprint(dbg, "The Puiseux Expansions have repeated initial coefficients. New algorithm not implemented for this case."); 3462 return(list()); 3463 } 3464 if((deg(sqpp) == 1) and (deg(pp) > 1)) 3465 { 3466 if((slN mod slD) == 0) 3467 { 3468 return(list("changeCoord", subst(sqpp, y, 0)*x^(slN div slD))); 3469 } else 3470 { 3471 "Not implemented."; 3472 return(list()); 3473 } 3474 } 3475 3476 if(slD*slN == 1){ 3477 dbprint(dbg, "Ordinary multiple point."); 3478 } 3479 return(list("OK", slN, slD)); 3480 } 3481 } 3482 3483 // Gives the integral basis in the desired shape. 3484 // It replaces the exponents alpha by the corresponding px^alpha 3485 static proc convertIB(list ib, poly px) 3486 { 3487 //"START - ibasis.lib - convertIB - 10"; 3488 int i; 3489 int expDen = ib[size(ib)][2]; 3490 poly den = px^expDen; 3491 ideal ibCom; 3492 for(i = 1; i<= size(ib); i++) 3493 { 3494 ibCom[i] = ib[i][1]*(px^(expDen-int(ib[i][2]))); 3495 } 3496 list new = list(ibCom, den); 3497 return(new); 3498 } 3499 3500 // Procedures to traslate polynomials 3501 static proc moveToVar(poly f, poly p, poly vari) 3502 { 3503 ////"START - ibasis.lib - moveToVar - 8"; 3504 matrix c = coeffs(p, vari); 3505 poly rootP = (-1)*c[1,1] / c[2,1]; 3506 poly fT = subst(f,vari,vari+rootP); 3507 return(fT); 3508 } 3509 3510 static proc moveFromVar(poly f, poly p, poly vari) 3511 { 3512 //"START - ibasis.lib - moveFromVar - 8"; 3513 matrix c = coeffs(p, vari); 3514 poly rootP = (-1)*c[1,1] / c[2,1]; 3515 poly fT = subst(f,vari,vari-rootP); 3516 return(fT); 3517 } 3518 3519 static proc moveTo(poly f, poly px, poly py) 3520 { 3521 //"START - ibasis.lib - moveTo - 8"; 3522 poly fT = moveToVar(f, px, var(1)); 3523 fT = moveToVar(fT, py, var(2)); 3524 return(fT); 3525 } 3526 3527 static proc moveFrom(poly f, poly px, poly py) 3528 { 3529 //"START - ibasis.lib - moveFrom - 8"; 3530 poly fT = moveFromVar(f, px, var(1)); 3531 fT = moveFromVar(fT, py, var(2)); 3532 return(fT); 3533 } 3534 3535 // Converts an integral basis in the shape {p0, p1, ..., pn-1} to the 3536 // shape (p0, d0), ..., (pn-1, dn-1) 3537 static proc intBasIdealToList(ideal I) 3538 { 3539 list ib; 3540 int d = deg(I[1], intvec(1,0)); 3541 list out; 3542 for(int i = 1; i <= ncols(I); i++) 3543 { 3544 out = divideBy(I[i], var(1)); 3545 ib[i] = list(out[1], d - out[2]); 3546 } 3547 return(ib); 3548 } 3549 3550 3551 // Divides f by the maximum possible power of g. 3552 // Returns the quotient and the exponent used of g. 3553 static proc divideBy(poly f, poly g) 3554 "USAGE: divideBy(f,g); f, g multivariate polynomials 3555 RETURN: a list of two elements. The first element is the polynomial f 3556 divided by the maximum possible power of g and the second element is an 3557 integer indicating the power of g used. 3558 KEYWORDS: division multivariate polynomials 3559 " 3560 3561 { 3562 int i = 1; 3563 ideal G = groebner(g); 3564 while(reduce(f, G) == 0) 3565 { 3566 f = f / g; 3567 i = i + 1; 3568 } 3569 list out = f, i-1; 3570 return(out); 3571 } 3572 3573 // Compares two polynomials in two variables. 3574 // This is used so that the puiseux expansions are always given in the same 3575 // order. 3576 static proc isBigger(poly f, poly g) 3577 { 3578 //"START - integralbasis.lib - isBigger - 1"; 3579 int i; 3580 intvec vy = (0,1); 3581 if(deg(f, vy) > deg(g, vy)) 3582 { 3583 // f is bigger 3584 return(1); 3585 } 3586 if(deg(f, vy) < deg(g, vy)) 3587 { 3588 // g is bigger 3589 return(-1); 3590 } 3591 matrix cf = coeffs(f, var(2)); 3592 matrix cg = coeffs(g, var(2)); 3593 for(i = size(cf); i >= 1; i = i-1) 3594 { 3595 if(cf[i,1] > cg[i,1]) 3596 { 3597 return(1); 3598 } 3599 if(cf[i,1] < cg[i,1]) 3600 { 3601 return(-1); 3602 } 3603 } 3604 // f is equal to g. 3605 return(0); 3606 } 3607 3608 // This is used so that the puiseux expansions are always given in 3609 // the same order. This procedure is also used in Puiseux library. 3610 static proc sortFactors(list facts) 3611 { 3612 //"START - integralbasis.lib - sortFactors - 1"; 3613 int i, j; 3614 int n = size(facts[1]); 3615 poly pTemp; 3616 int eTemp; 3617 for (i = n; i >= 1; i--) 3618 { 3619 for (j = 1; j <= i-1; j++) 3620 { 3621 if(isBigger(facts[1][j], facts[1][j+1]) == 1) 3622 { 3623 pTemp = facts[1][j]; 3624 eTemp = facts[2][j]; 3625 facts[1][j] = facts[1][j+1]; 3626 facts[2][j] = facts[2][j+1]; 3627 facts[1][j+1] = pTemp; 3628 facts[2][j+1] = eTemp; 3629 } 3630 } 3631 } 3632 return(facts); 3633 } 3634 3635 294 3636 /////////////////////////////////////////////////////////////////////////////// 295 3637 296 static proc integralLocal(ideal I, list #){ 297 // Computes the integral basis by localizing at the different components of 298 // the singular locus. 3638 // Convert a list of numbers into an intvec 3639 static proc poly2intvec(poly p) 3640 { 3641 intvec c; 3642 matrix M = coef(p, var(1)); 3643 int n = ncols(M); 3644 for(int i = 1; i <= n; i++) 3645 { 3646 c[i] = int(deg(M[1,n+1-i])); 3647 } 3648 return(c); 3649 } 3650 3651 /////////////////////////////////////////////////////////////////////////////// 3652 3653 // Convert a list of numbers into an intvec 3654 static proc list2intvec(list l) 3655 { 3656 intvec c; 3657 for(int i = 1; i <= size(l); i++) 3658 { 3659 c[i] = int(l[i]); 3660 } 3661 return(c); 3662 } 3663 3664 /////////////////////////////////////////////////////////////////////////////// 3665 3666 // Given two intvecs, both ordered for lowest to highest, it return 3667 // a new intvec containing the union of both intvecs, ordered from lowest 3668 // to highest. 3669 static proc appendIntvecs(intvec a, intvec b) 3670 { 3671 intvec c; 3672 int indA = 1; 3673 int indB = 1; 3674 int indC = 1; 3675 int last = -1; 3676 while((indA <= size(a)) and (indB <= size(b))) 3677 { 3678 if(a[indA] < b[indB]){ 3679 if(a[indA] > last) 3680 { 3681 c[indC] = a[indA]; 3682 last = c[indC]; 3683 indC++; 3684 } 3685 indA++; 3686 } else { 3687 if(b[indB] > last) 3688 { 3689 c[indC] = b[indB]; 3690 last = c[indC]; 3691 indC++; 3692 } 3693 indB++; 3694 } 3695 } 3696 while(indA <= size(a)) 3697 { 3698 if(a[indA] > last) 3699 { 3700 c[indC] = a[indA]; 3701 last = c[indC]; 3702 indC++; 3703 } 3704 indA++; 3705 } 3706 while(indB <= size(b)) 3707 { 3708 if(b[indB] > last) 3709 { 3710 c[indC] = b[indB]; 3711 last = c[indC]; 3712 indC++; 3713 } 3714 indB++; 3715 } 3716 return(c); 3717 } 3718 3719 3720 // Computes a Groebner basis of P with lex order and y > x. 3721 static proc yInTermOfx(ideal P) 3722 { 3723 //"START - integralbasis.lib - yInTermOfx - 1"; 3724 def R = basering; 3725 ring S = 0, (var(2), var(1)), lp; 3726 ideal P = imap(R, P); 3727 P = groebner(P); 3728 setring R; 3729 P = imap(S, P); 3730 return(P); 3731 } 3732 3733 // Divides a polynomial by a - x. 3734 static proc divXA(poly f) 3735 { 3736 //"START - integralbasis.lib - divXA"; 3737 def R = basering; 3738 3739 ring W = 0, (@a,var(1),var(2)), lp; 3740 poly f = imap(R, f); 3741 //list l = division(f, @a-x); 3742 list l = division(f, @a-var(2)); 3743 setring R; 3744 list l = imap(W, l); 3745 list l2 = l[1][1,1], l[2][1]; 3746 return(l2); 3747 } 3748 3749 static proc swapXYIdeal(ideal I) 3750 { 3751 //"START - integralbasis.lib - swapXYIdeal"; 3752 def R = basering; 3753 def R2 = ring(0, (y,x), dp); 3754 setring R2; 3755 ideal I = fetch(R, I); 3756 setring R; 3757 I = imap(R2, I); 3758 return(I); 3759 } 3760 3761 static proc swapXYPoly(poly f) 3762 { 3763 //"START - integralbasis.lib - swapXYPoly"; 3764 def R = basering; 3765 def R2 = ring(0, (y,x), dp); 3766 setring R2; 3767 poly f = fetch(R, f); 3768 setring R; 3769 f = imap(R2, f); 3770 return(f); 3771 } 3772 3773 // f monic as poly in the second variable (assuming that the coefficient of 3774 // the max degree is a constant) 3775 proc monic(poly f) 3776 "USAGE: monic(f); f polynomial in two variables whose leadi. 3777 RETURN: a multiple of f monic as polynomial in the second variables, 3778 polynomial of degree d in the second variable of the ring with 3779 an ordinary multiple point at the origin of order k. 3780 ASSUME: f is a bivariate polynomial whose leading coefficients as 3781 polynomial in the second variable is a unit. 3782 EXAMPLE: example monic; shows an example 3783 " 3784 { 3785 //"START - integralbasis.lib - monic - 1"; 3786 matrix c = coeffs(f,var(2)); 3787 f = f/c[size(c), 1]; 3788 return(f); 3789 } 3790 example 3791 { "EXAMPLE:"; 3792 echo = 2; 3793 ring R = 0, (x,y), dp; 3794 poly f = -3y3 + 3x2y + y2 + 1; 3795 monic(f); 3796 } 3797 3798 3799 3800 // Generates a polynomial of degree d in y with a ordinary multiple point at 3801 // the origin of order k. 3802 proc polyDK(int d, int k, list #) 3803 "USAGE: polyDK(d,k,#); d integer, k<=d integer. 3804 RETURN: polynomial of degree d in the second variable of the ring with 3805 an ordinary multiple point at the origin of order k. 3806 KEYWORDS: singularities ordinary multiple point. 3807 EXAMPLE: example polyDK; shows an example 3808 " 3809 3810 { 3811 //"START - integralbasis.lib - polyDK"; 3812 if(size(#) > 0){ 3813 if(typeof(#[1]) == "int"){ 3814 int sd = #[1]; 3815 //"Setting the seed to ", sd; 3816 system("--random", sd); 3817 } 3818 } 3819 299 3820 int i; 300 int dbg = printlevel - voice + 4; 3821 def r = basering; 3822 ring s = 0, (x,y,z), dp; 3823 ideal m2 = maxideal(d); 3824 ideal m1 = ideal(x,y); 3825 m1 = m1^k; 3826 ideal J = intersect(m1, m2); 3827 3828 int good = 0; 3829 while(good == 0){ 3830 setring s; 3831 matrix M = randommat(1,1,J,5); 3832 poly p = M[1,1]; 3833 p = p+y^(d); 3834 p = subst(p,z,1); 3835 3836 setring r; 3837 poly p = fetch(s, p); 3838 matrix c = coeffs(p,y); 3839 poly f = p / c[size(c), 1]; 3840 3841 // We check if f satisfies the desired properties. 3842 list fc = divideBy(subst(f,x,0), y); 3843 if(fc[2] == k){ 3844 good = 1; 3845 } 3846 } 3847 return(f); 3848 } 3849 example 3850 { "EXAMPLE:"; 3851 echo = 2; 3852 ring R = 0, (x,y), dp; 3853 int k = 3; 3854 int d = 6; 3855 3856 // Polynomial of degree 6 in y with an ordinary multiple point 3857 // at the origin of order k. 3858 poly f = polyDK(d, k, 1231); 3859 f; 3860 3861 // The integral basis of R / <f> 3862 list l = integralBasis(f, 2, "atOrigin"); 3863 l; 3864 echo = 0; 3865 } 3866 3867 3868 3869 ///////////////////////////////////////////////////////////////////////////// 3870 // 3871 // Hensel Lifting 3872 // 3873 ///////////////////////////////////////////////////////////////////////////// 3874 3875 proc henselGlobal(poly f, poly g, poly h, int order) 3876 "USAGE: henselGlobal(f,g,h,order); h is polynomial in x and y. 3877 f and g are polynomials in y such that f(y)*g(y) = h(0,y) and <f, g> = 1. 3878 RETURN: polynomials f1 and g1 such that 3879 1) h = f1*g1 up to the required order in x. 3880 2) f1(0,y) = f, g1(0,y) = g 3881 KEYWORDS: hensel lifting. 3882 " 3883 { 3884 //"START - hensel.lib - henselGlobal - 1"; 3885 intvec vx = (1,0); 3886 3887 int dbg = printlevel - voice + 2; 3888 //if(dbg > 2) 3889 //{ 3890 // "Hensel lifting input:"; 3891 // "f: ", f; "g: ", g; "h: ", h; 3892 // "order: ", order; 3893 //} 3894 3895 // Trivial cases 3896 //if(f == 1) 3897 if(deg(f,intvec(0,1)) == 0) 3898 { 3899 //if(f != 1) 3900 //{ 3901 // "Non monic at henselGlobal, please check."; 3902 //} 3903 if(subst(h, var(1), 0) == f * g) 3904 { 3905 list L = f, jet(h, order, vx); 3906 //dbprint(dbg - 2, "Output: ", L); 3907 //"DBG - henselGlobal easy ends"; 3908 return(L); 3909 } else 3910 { 3911 "ERROR"; 3912 ~; 3913 ERROR("f(y)*g(y) != h(0,y)"); 3914 } 3915 } 3916 //if(g == 1) 3917 if(deg(g, intvec(0,1)) == 0) 3918 { 3919 //if(g != 1) 3920 //{ 3921 // "Non monic at henselGlobal, please check."; 3922 //} 3923 if(subst(h, var(1), 0) == f * g) 3924 { 3925 list L = jet(h, order, vx), poly(1); 3926 //"DBG - henselGlobal easy ends"; 3927 //dbprint(dbg - 2, "Output: ", L); 3928 return(L); 3929 } else 3930 { 3931 "ERROR"; 3932 ~; 3933 ERROR("f(y)*g(y) != h(0,y)"); 3934 } 3935 } 3936 3937 int t = timer; 3938 // Kernel version 3939 dbprint(dbg, "--------Calling Hensel lifting (kernel)..."); 3940 //"DBG - Calling hensel lifting (kernel)..."; "h: ", h; "f: ", f; "g:", g; 3941 3942 // DEBUG!! 3943 // REMOVE!!! 3944 //order = order * 10; 3945 3946 //"h, order, f, g", h, order, f, g; 3947 list L = factmodd(h, order, f, g, 1, 2); 3948 3949 //list L = system("henselfactors", 1, 2, h, f, g, order); 3950 debug_log_intbas(3, "--------Time hensel lifting (kernel): ", timer-t); 3951 //"DBG - Time hensel lifting (kernel): ", timer-t; 3952 3953 dbprint(dbg - 2, "--------Output of Hensel lifting: ", L); 3954 //"DBG - henselGlobal ends"; 3955 //"Check: "; jet(L[1]*L[2] - h, order, vx); 3956 return(L); 3957 } 3958 example 3959 { "EXAMPLE:"; 3960 echo = 2; 3961 ring R = 0, (x,y), dp; 3962 3963 // Polynomial of degree 6 in y with an ordinary multiple point 3964 // at the origin of order k. 3965 poly h = (y2 + 3xy + x3 + x4)*(y3 + 2x + 1); 3966 poly f = y2; 3967 poly g = y3 + 1; 3968 henselGlobal(f, g, h, 3); 3969 echo = 0; 3970 } 3971 3972 3973 3974 3975 // This procedure separates the segment with slope slN / slD (assuming that 3976 // it is the smallest slope) from the rest. 3977 // It returns a list containing the factor correspoding to the slope slN / slD, and 3978 // the polynomial corresponding to all the factors with larger slope. 3979 // This procedure tranforms the polynomials so that the Hensel Lifting Lemma 3980 // can be applied, and uses it to lift the factorization up to the desired 3981 // order. 3982 static proc henselLocal(poly f, int slN, int slD, int order) 3983 { 3984 int dbg = printlevel - voice + 5; 3985 int i; 3986 intvec vy = 0, 1; 3987 poly x = var(1); 3988 poly y = var(2); 3989 int d = deg(f, vy); 3990 3991 //"Transformation...", slN, slD; 3992 3993 // We transform y by x^(slN / slD)y in f. 3994 // and factor out the powers of x. 3995 // (In fact, to avoid fractional exponents, 3996 // we map x to x^slD and y to x^slN*y.) 3997 poly f1 = mapTo(f, slN, slD); 3998 int fD = slN * d; 3999 f1 = f1 / (x^fD); 4000 poly f0 = subst(f1, x, 0); 4001 list l1 = divideBy(f0, y); 4002 poly g0 = l1[1]; 4003 int gD = deg(g0, vy); 4004 int hD = l1[2]; 4005 poly h0 = y^hD; 4006 4007 // We set up to which order we have to compute the expansions 4008 int ordCommon; 4009 if(hD < gD) 4010 { 4011 ordCommon = slN * hD; 4012 } else 4013 { 4014 ordCommon = slN * gD; 4015 } 4016 4017 //dbprint(dbg, "henselGlobal inside henselLocal"); 4018 //dbprint(dbg - 1, "Order: ", order * slD - ordCommon); 4019 4020 // DEBUG!!! 4021 //order = order * 10; 4022 4023 list l2 = henselGlobal(g0, h0, f1, order * slD - ordCommon); 4024 //dbprint(dbg, "henselGlobal inside henselLocal finished"); 4025 4026 // We transform everything back to the original setting 4027 // The case of several blocks with the same slope is not implemented. 4028 //list comps = henselFacs(g, order * slD - ordCommon); 4029 poly g = l2[1] * (x^(gD * slN)); 4030 4031 g = mapFrom(g, slN, slD); 4032 4033 poly h = l2[2] * (x^(hD*slN)); 4034 h = mapFrom(h, slN, slD); 4035 return(list(g, h)); 4036 } 4037 4038 // Maps x to x^slD and y to x^slN*y. 4039 static proc mapTo(poly f, int slN, int slD) 4040 { 4041 f = subst(f, var(1), var(1)^slD); 4042 f = subst(f, var(2), var(1)^slN*var(2)); 4043 return(f); 4044 } 4045 4046 // We map back x^slN*y to y and x^slD to x. 4047 static proc mapFrom(poly f, int slN, int slD) 4048 { 4049 //"START - hensel.lib - mapFrom - 1"; 301 4050 def R = basering; 302 303 list n; // Output of proc normal 304 ideal norT; // Temporary data. 305 poly denomT; // Temporary data. 306 307 ideal nor; // Output of normal with the denominator changed to the 308 // common denominator. 309 ideal res; // The full integral basis 310 311 //--------------------------- read the input options--------------------------- 312 int denomOption = 0; 313 for ( i=1; i <= size(#); i++ ) 314 { 315 if ( typeof(#[i]) == "string" ) 316 { 317 if (#[i]=="var1") 318 {denomOption = 1;} 319 if (#[i]=="var2") 320 {denomOption = 2;} 321 } 322 } 323 324 //------------------------ singular locus computation ------------------------- 325 // We use a general method that works for any ideal. 326 // For I defined by a single polynomial a simpler method could be used. 327 list IM = mstd(I); 328 I = IM[1]; 329 int d = dim(I); 330 ideal IMin = IM[2]; 331 qring Q = I; // We work in the quotient by the Groebner basis of the ideal I 332 option("redSB"); 333 option("returnSB"); 334 ideal I = fetch(R, I); 335 attrib(I, "isSB", 1); 336 ideal IMin = fetch(R, IMin); 337 if(dbg >= 2){ 338 int t = timer; 339 } 340 ideal J = minor(jacob(IMin), nvars(basering) - d, I); 341 if(dbg >= 2){ 342 "singular locus time: ", timer - t; 343 t = timer; 344 } 4051 int jj = attrib(basering, "maxExp"); 4052 ring S = (0, @a), (x, y, T), (dp, L(jj)); 4053 poly f = fetch(R, f); 4054 ideal I1 = x^slN*y-T; 4055 poly g = reduce(f, groebner(I1)); 4056 g = subst(g, T, y); 4057 ideal I2 = x^slD - T; 4058 g = reduce(g, groebner(I2)); 4059 g = subst(g, T, x); 345 4060 setring R; 346 ideal J = fetch(Q, J); 347 J = J, I; 348 J = groebner(J); 349 350 if(dbg >= 2){ 351 "groebner of the singular locus time: ", timer - t; 352 t = timer; 353 } 354 355 if(dbg >= 2){ 356 "The original singular locus is"; 357 J; 358 } 359 360 //------------------------ universal denominator ------------------------------ 361 // We could use the LCD of the denominators of each component, but we need 362 // a denominator in the required variable. 363 if(denomOption == 0){ 364 poly condu = getSmallest(J); // Choses the polynomial of smallest degree 365 // of J as universal denominator. 4061 poly g = fetch(S, g); 4062 //"ENDS - hensel.lib - mapFrom - 1"; 4063 return(g); 4064 } 4065 4066 //------------------------------------------------------------------ 4067 // General procedure for computing factors via hensel lifting 4068 //------------------------------------------------------------------ 4069 // Computes the factors of f corresponding to the Puiseux blocks up to a given 4070 // order in the power series ring. 4071 static proc henselBlocks(poly f, int globOrder, int loc) 4072 { 4073 int dbg = printlevel - voice + 5; 4074 4075 // If loc = 1, the factors outside the origin will be taken all together. 4076 // The first poly in the ouput will be the factor corresponding to the component 4077 // outside the origin. 4078 4079 //if(dbg > 5) 4080 //{ 4081 // "---- henselBlock begins"; 4082 //} 4083 4084 poly x = var(1); 4085 poly y = var(2); 4086 4087 int comp = 1; 4088 list comps; 4089 list compsT; 4090 int i, j, k; 4091 int first; 4092 int stop, last; 4093 4094 list fSegment; 4095 4096 intvec vx = (1,0); 4097 intvec vy = (0,1); 4098 int maxOrder = deg(f, vx); 4099 if(globOrder > maxOrder) 4100 { 4101 maxOrder = globOrder; 4102 } 4103 int locOrder = maxOrder; 4104 4105 if(loc == 1) 4106 { 4107 poly f0 = subst(f, x, 0); 4108 4109 list fl = divideBy(f0, y); 4110 4111 list fGlob = henselGlobal(y^fl[2], fl[1], f, maxOrder); 4112 4113 poly fLoc = fGlob[1]; 4114 4115 if(fLoc == 1) 4116 { 4117 "Warning! No local component. This may indicate you are computing the basis at a value of X where there is no singularity."; 4118 } 4119 comps[1] = fGlob[2]; // comp[1] is the component outside the origin. 4120 comp = 2; 4121 dbprint(dbg, "----Computing Puiseux Segments..."); 4122 fSegment = henselSegments(fLoc, maxOrder); 4123 4124 for(i = 1; i <= size(fSegment); i++) 4125 { 4126 compsT = henselInSegment(fSegment[i], maxOrder); 4127 4128 for(k = 1; k <= size(compsT); k++){ 4129 comps[comp] = compsT[k]; 4130 comp++; 4131 } 4132 } 4133 } else 4134 { 4135 comps = henselTotal(f, maxOrder); 4136 comp = size(comps) + 1; 4137 } 4138 4139 return(comps); 4140 } 4141 4142 // Given a poly without components outside the origin, computes the factors 4143 // corresponding to each slope in the power series rings. 4144 static proc henselSegments(poly f, int order) 4145 { 4146 //if(printlevel - voice > 5) 4147 //{ 4148 // "START - hensel.lib - henselSegments - 1"; 4149 //} 4150 4151 int dbg = printlevel - voice + 5; 4152 int i; 4153 int slN, slD; 4154 poly fLoc = f; 4155 list lLoc; 4156 4157 list l = newtonpoly(f); 4158 list hSegment; 4159 4160 for(i = 1; i < size(l) - 1; i++) 4161 { 4162 slN = l[i+1][1] - l[i][1]; 4163 slD = l[i][2] - l[i+1][2]; 4164 4165 // The polynomial corresponding to the segment. 4166 if(dbg > 0) 4167 { 4168 "------Computing the polynomial corresponding to segment", i; 4169 } 4170 lLoc = henselLocal(fLoc, slN, slD, order); 4171 4172 //dbprint(dbg, "Done."); 4173 hSegment[i] = lLoc[1]; 4174 fLoc = lLoc[2]; 4175 } 4176 hSegment[size(l) - 1] = fLoc; 4177 4178 return(hSegment); 4179 } 4180 4181 // Computes the different blocks in a segment up to the given order. 4182 static proc henselInSegment(poly f, int globOrder) 4183 { 4184 //if(printlevel - voice > 5) 4185 //{ 4186 // "START - hensel.lib - henselSegments - 1"; 4187 //} 4188 int i, j; 4189 int loc; 4190 list comps; 4191 4192 poly x = var(1); 4193 poly y = var(2); 4194 intvec vx = (1,0); 4195 intvec vy = (0,1); 4196 int d = deg(f, vy); 4197 4198 list l = newtonpoly(f); 4199 4200 int slN = l[2][1] - l[1][1]; 4201 int slD = l[1][2] - l[2][2]; 4202 int g = gcd(slD, slN); 4203 slD = slD div g; 4204 slN = slN div g; 4205 4206 poly je = Puiseuxexpansions::minEqNewton(f, slN, slD); 4207 list fJe = factorize(je); 4208 fJe = sortFactors(fJe); 4209 4210 // We transform y by x^(slN / slD)y in f. 4211 // and factor out the powers of x. 4212 // (In fact, to avoid fractional exponents, 4213 // we map x to x^slD and y to x^slN*y.) 4214 poly f1 = mapTo(f, slN, slD); 4215 f1 = f1 / (x^(d*slN)); 4216 4217 poly je1 = mapTo(je, slN, slD); 4218 je1 = je1 / (x^(d*slN)); 4219 4220 // For each factor of the equation, compute the corresponding lifted factor 4221 list lLoc; 4222 poly fLoc = f1; 4223 list hFactor; 4224 poly fJe1; 4225 int sFac = size(fJe[1]) - 1; 4226 4227 for(i = 1; i < sFac; i++) 4228 { 4229 fJe1 = mapTo(fJe[1][i+1]^(fJe[2][i+1]), slN, slD); 4230 fJe1 = fJe1 / (x^(deg(fJe1, vy) * slN)); 4231 je1 = je1 / fJe1; 4232 lLoc = henselGlobal(fJe1, je1, fLoc, globOrder); 4233 hFactor[i] = lLoc[1]; 4234 fLoc = lLoc[2]; 4235 } 4236 hFactor[sFac] = fLoc; 4237 4238 int degFac; 4239 int comp = 1; 4240 poly ratPart; 4241 list compsT; 4242 for(i = 1; i <= sFac; i++) 4243 { 4244 degFac = deg(fJe[1][i+1], vy) * fJe[2][i+1]; 4245 hFactor[i] = hFactor[i] * (x^(degFac * slN)); 4246 hFactor[i] = mapFrom(hFactor[i], slN, slD); 4247 compsT = splitFact(hFactor[i], fJe[1][i+1], fJe[2][i+1], globOrder); 4248 for(j = 1; j <= size(compsT); j++) 4249 { 4250 comps[comp] = compsT[j]; 4251 comp++; 4252 } 4253 } 4254 return(comps); 4255 } 4256 4257 // Computes the Puiseux block at the origin an outside the origin. 4258 // It lifts all the factors of h(0,y) and splits them. 4259 static proc henselTotal(poly h, int order) 4260 { 4261 if(printlevel - voice > 5) 4262 { 4263 "START - hensel.lib - henselTotal"; 4264 } 4265 4266 poly f, g; 4267 int i, j; 4268 list facs; 4269 list comps; 4270 list hFacts; 4271 int comp = 1; 4272 4273 poly x = var(1); 4274 poly y = var(2); 4275 intvec vy = (0,1); 4276 4277 poly h0 = subst(h, x, 0); 4278 list fc = factorize(h0); 4279 fc = sortFactors(fc); 4280 4281 g = h; 4282 4283 // Computes the lifting of the factors 4284 list compsT; 4285 for(i = 2; i < size(fc[1]); i++) 4286 { 4287 f = fc[1][i]^(fc[2][i]); 4288 g = g / f; 4289 facs = henselGlobal(f, g, h, order); 4290 h = facs[2]; 4291 hFacts[i-1] = facs[1]; 4292 } 4293 hFacts[size(fc[1]) - 1] = h; 4294 4295 // Splits the factors 4296 for(i = 1; i <= size(hFacts); i++) 4297 { 4298 compsT = splitFact(hFacts[i], fc[1][i+1], fc[2][i+1], order); 4299 for(j = 1; j <= size(compsT); j++) 4300 { 4301 comps[comp] = compsT[j]; 4302 comp++; 4303 } 4304 } 4305 return(comps); 4306 } 4307 4308 // Split poly f assuming that it corresponds to a factor factor^exp 4309 static proc splitFact(poly f, poly fact, int exp, int order) 4310 { 4311 poly x = var(1); 4312 poly y = var(2); 4313 4314 fact = monic(fact); 4315 int i, j; 4316 list comps; 4317 4318 intvec vy = (0,1); 4319 int comp = 1; 4320 4321 // If the degree of the minimal polynomial is greater than 1, 4322 // the splitting is not implemented. 4323 4324 // If the degree is 1, and the exponent is 1, there is nothing to do. 4325 if((deg(fact, vy) == 1) and (exp > 1)) 4326 { 4327 // The rational part. 4328 fact = monic(fact); 4329 poly ratPart = subst(fact, y, 0); 4330 poly fNew = subst(f, y, y - ratPart); 4331 4332 int loc; 4333 int start; 4334 if(fact == y) 4335 { 4336 loc = 1; // Separate only the factors at the origin. 4337 start = 2; 4338 } else 4339 { 4340 loc = 0; // Separate also the factors outside the origin. 4341 start = 1; 4342 } 4343 list compsT = henselBlocks(fNew, order, loc); 4344 for(j = start; j <= size(compsT); j++) 4345 { 4346 comps[comp] = subst(compsT[j], y, y + ratPart); 4347 comp++; 4348 } 4349 } else 4350 { 4351 comps[1] = f; 4352 } 4353 return(comps); 4354 } 4355 4356 /////////////////////////////////////////////////////////////////////// 4357 // 4358 // Auxiliary tools 4359 // 4360 /////////////////////////////////////////////////////////////////////// 4361 4362 // Checks if the term of highest degree in y of f contains x. 4363 static proc isXMonic(poly f){ 4364 //"START - integralbasis.lib - isXMonic"; 4365 matrix c = coeffs(f,var(2)); 4366 return(deg(c[size(c), 1]) == 0); 4367 } 4368 4369 // Check if the only singularity is at the origin 4370 static proc checkAt0(poly f, int modular) 4371 { 4372 def R = basering; 4373 4374 int vdDS, vd32003; 4375 int vdx, vdy; 4376 4377 // vdim at origin (using ds ordering) 4378 //"checking at 0"; 4379 list rlDS = ringlist(R); 4380 rlDS[3] = list(list("C", 0), list("ds", intvec(1,1))); 4381 def S1 = ring(rlDS); 4382 setring S1; 4383 poly f = imap(R, f); 4384 ideal SL = f, diff(f, var(1)), diff(f, var(2)); 4385 4386 if(modular == 0) 4387 { 4388 SL = groebner(SL); 366 4389 } else { 367 poly condu = getOneVar(J, denomOption); 368 } 369 370 //------------------- components of the singular locus------------------------ 371 list pd = primdecGTZ(J); 372 if(dbg >= 2){ 373 "primary decomposition time:", timer - t; 374 } 375 if(dbg >= 1){ 376 "The number of components of the Singular Locus is ", size(pd); 377 } 378 379 // The following commented lines are not needed for integral basis, since 380 // all components are maximal. 381 // Computes the maximal components and the components included in them 382 //list comps = maxComps(pd); 383 // For each maximal component, it intersects all the components included in it 384 //list locs = intersectList(comps); 385 386 //------------------- normalization of each component-------------------------- 387 list opts; 388 for(i = 1; i <= size(pd); i++){ 389 //opts = #; 390 // We use the prime components as test ideals in the normalization. 391 //opts = list(list("inputJ", pd[i][2])); 392 // We use the primary components as conductor in the normalization. 393 opts = list(list("inputC", pd[i][1])); 394 395 if(dbg >= 2){ 396 t = timer; 397 } 398 n = normal(I, opts); 399 if(dbg >= 2){ 400 "normalization of component ", i, " time: ", timer - t; 401 } 402 if(size(n[2]) > 1){ 403 ERROR("The input polynomial is not irreducible."); 404 } 405 406 // We add up the normalizations at each localization, to construct the 407 // normalization of the whole ideal. 408 norT = n[2][1]; 409 denomT = norT[size(norT)]; 410 411 // We change the denominator of the normalization of the localized ring, 412 // to have the same denominator for all the normalizations. 413 nor = changeDenominator(norT, denomT, condu, I); 414 415 // We sum the result to the previous results. 416 res = res, nor; 417 } 418 res = groebner(res); 419 res[size(res)+1] = condu; 420 421 // The output follows the output of proc normal, but we don't return the 422 // ring structure, only the generators. (We return 0 instead of the ring.) 423 return(list(0,list(res))); 424 } 425 4390 SL = modStd(SL); 4391 } 4392 vdDS = vdim(SL); 4393 setring R; 4394 4395 // vdim at affine ring (using char 32003) 4396 list rl32003 = ringlist(R); 4397 rl32003[1] = 32003; 4398 def S2 = ring(rl32003); 4399 setring S2; 4400 poly f = imap(R, f); 4401 ideal SL = f, diff(f, var(1)), diff(f, var(2)); 4402 SL = groebner(SL); 4403 vd32003 = vdim(SL); 4404 setring R; 4405 if(vdDS == vd32003) 4406 { 4407 4408 // vdim at charts (using char 32003) 4409 ring S = 0, (x,y,z), dp; 4410 poly f = fetch(R, f); 4411 f = homog(f, z); 4412 4413 poly fy = subst(f, y, 1); 4414 poly fx = subst(f, x, 1); 4415 4416 ring Sx = 32003, (y, z), dp; 4417 poly fx5 = imap(S, fx); 4418 ideal J = fx5, diff(fx5, y), diff(fx5, z); 4419 J = groebner(J); 4420 vdx = vdim(J); 4421 4422 ring Sy = 32003, (x, z), dp; 4423 poly fy5 = imap(S, fy); 4424 ideal J = fy5, diff(fy5, x), diff(fy5, z); 4425 J = groebner(J); 4426 vdy = vdim(J); 4427 4428 if((vdx == 0) && (vdy == 0)) 4429 { 4430 // No singularities at infinity 4431 return(1); 4432 } else 4433 { 4434 // Singularities at infinity 4435 "Singularities at infinity"; 4436 return(0); 4437 } 4438 } else 4439 { 4440 "Check at origin: FALSE"; 4441 return(0); 4442 } 4443 kill vdDS, vd32003; 4444 kill S1, S2; 4445 kill rlDS, rl32003; 4446 } 4447 4448 static proc xCondu(poly px, list norOut, ideal I) 4449 { 4450 ideal XC = quotient(norOut[2]+I, norOut[1]); 4451 ideal XCX = eliminate(XC, var(2)); 4452 //"The x-conductor is ", XCX[1]; 4453 return(XCX[1]); 4454 } 4455 4456 // Compose the tower of minimimal polynomials. 4457 // We assume that the polynomials are given in the second variable. 4458 // The first polynomial in the list is not used. 4459 static proc composePolys(list minPolys) 4460 { 4461 int i; 4462 poly mp = minPolys[size(minPolys)]; 4463 for(i = size(minPolys)-1; i > 1; i--) 4464 { 4465 mp = subst(mp, var(2), minPolys[i]); 4466 } 4467 return(mp); 4468 } 4469 4470 // We work in a ring extension from a ring extension, and we compute the 4471 // coefficients of f in the original ring (we assume they are elements of the 4472 // original ring). 4473 // poly alpha is the primitive element of the first extension mapped into the 4474 // extended ring 4475 // d is the degree of the original extension 4476 static proc extendBack(poly f, poly alpha, int d) 4477 { 4478 def R = basering; 4479 ideal I; 4480 for(int i = 1; i <= d; i++) 4481 { 4482 I[i] = alpha^(i-1); 4483 } 4484 4485 ring S = 0, (var(1), var(2), @a), dp; 4486 poly f = imap(R, f); 4487 ideal I = imap(R, I); 4488 module M = coeffs(I, @a); 4489 matrix CC = coef(f, var(1)*var(2)); 4490 module P; 4491 matrix L; 4492 int j; 4493 ideal rel; 4494 for(i = 1; i <= ncols(CC); i++) 4495 { 4496 P = coeffs(CC[2, i], @a); 4497 L = lift(M, P); 4498 rel[i] = 0; 4499 for(j = 1; j <= nrows(L); j++) 4500 { 4501 rel[i] = rel[i] + L[j, 1] * var(1)^(j-1); 4502 } 4503 4504 } 4505 setring R; 4506 ideal rel = imap(S, rel); 4507 return(rel); 4508 } 4509 4510 static proc changeDenominatorFast(ideal U1, poly c1, poly c2, ideal I) 4511 { 4512 //"changeDenominatorFast"; 4513 ideal U2 = quotient(c2*U1+I, c1); 4514 return(U2); 4515 } 4516 4517 static proc trivialBasis(poly f) 4518 { 4519 int j; 4520 4521 intvec vy = (0, 1); 4522 int n = deg(f, vy); 4523 ideal l; 4524 4525 for(j = 0; j < n; j++) 4526 { 4527 l[j+1] = var(2)^j; 4528 } 4529 return(list(l, poly(1))); 4530 } 4531 4532 static proc isOneIdeal(ideal I) 4533 { 4534 I = groebner(I); 4535 int i; 4536 int out = 0; 4537 4538 for (i = 1; i <= ncols(I); i++) 4539 { 4540 if(I[i] == 1){out = 1;} 4541 } 4542 return(out); 4543 } 4544 4545 static proc isZeroIdeal(ideal I) 4546 { 4547 int i; 4548 int out = 1; 4549 for (i = 1; i <= ncols(I); i++) 4550 { 4551 if(I[i] != 0){out = 0;} 4552 } 4553 return(out); 4554 } 4555 4556 //////////////////////////////////////////////////////////////////////////////// 4557 // SPECIAL ALGORITHM FOR SINGULARITIES WITH SAME X-COORDINATE 4558 //////////////////////////////////////////////////////////////////////////////// 4559 4560 // Case: singularity with non-rational Y coordinate, and X = 0. 4561 // py is a polynomial in Y, whose roots are the Y-coordinate of the 4562 // singuarities. 4563 static proc ibNonRatY(poly f, poly py, int locBasis){ 4564 // We have singularities at <x, roots of(py)>. 4565 int i; 4566 int b; // Multiplicity of the singularity. 4567 int dbg = printlevel - voice + 5; 4568 4569 poly x = var(1); 4570 poly y = var(2); 4571 intvec vY = (0,1); 4572 intvec vX = (1,0); 4573 4574 def R = basering; 4575 int d = deg(f,vY); 4576 4577 // We add one of the roots of py to the basering. 4578 def S = splitRingAt(py); 4579 setring S; 4580 poly f = fetch(R, f); 4581 poly py = fetch(R, py); 4582 4583 // Initial terms of the Puiseux expansion of f at the singularity, y = PE. 4584 poly PE = par(1); 4585 4586 // We move the singularity to the origin 4587 poly fT = subst(f, var(2), var(2) + par(1)); 4588 4589 // We compute the integral basis with the singularity at the origin. 4590 list ib = ibNonRatYSplit(fT, f, py, PE, locBasis); 4591 4592 // We do not need to move back the integral basis, because it is already 4593 // computed using the original f. 4594 4595 // Back to the original ring 4596 setring R; 4597 list ib = imap(S, ib); 4598 return(ib); 4599 } 4600 4601 // fOrig and py are the original polynomials, they will not be changed. 4602 // f and PE are changed so as to compute the puiseux expansions 4603 static proc ibNonRatYSplit(poly f, poly fOrig, poly py, poly PE, int locBasis) 4604 { 4605 debug_log_intbas(4, "--------START - integralbasis.lib - ibLocalNonRatYSplit"); 4606 // "f", f; 4607 // "fOrig", fOrig; 4608 // "py", py; 4609 // "PE", PE; 4610 // "locBasis", locBasis; 4611 // "basering", basering; 4612 4613 int i; 4614 int dbg = printlevel - voice + 5; 4615 4616 poly x = var(1); 4617 poly y = var(2); 4618 4619 intvec vY = (0,1); 4620 intvec vX = (1,0); 4621 int d = deg(fOrig,vY); 4622 4623 // We compute the multiplicity of the singularity. 4624 poly f0 = subst(fOrig,x,0); 4625 list fc = divideBy(f0, py); 4626 int b = fc[2]; 4627 4628 list dat = newtonInfo(f, b); 4629 4630 list ib; // Integral basis 4631 if(size(dat) == 0){ 4632 // The simple algorithm cannot be used. 4633 return(list()); 4634 } 4635 if(dat[1] == "changeCoord") 4636 { 4637 // The first term of the Puiseux expansions is repeated. 4638 // We remove it and compute the integral basis recursively. 4639 //"DBG - Change coord (linear term in PE)"; 4640 f = subst(f, y, y - dat[2]); 4641 4642 // We add the new terms of the Puiseux expansion 4643 PE = PE - dat[2]; 4644 4645 // We compute the integral basis 4646 ib = ibNonRatYSplit(f, fOrig, py, PE, locBasis); 4647 4648 if(size(ib) > 0) 4649 { 4650 return(ib); 4651 } else 4652 { 4653 // The integral basis could not be computed. 4654 return(list()); 4655 } 4656 } 4657 4658 // We run the algorithm 4659 dbprint(dbg, "Simple algorithm is used for this component."); 4660 4661 poly f1, f2; // fOrig(0,y) = f1*f2 4662 f1 = py^b; 4663 f2 = fc[1]; 4664 4665 // Slope of the Newton polygon (giving the initial exponent) 4666 int slN = dat[2]; 4667 int slD = dat[3]; 4668 4669 // Degrees of the polynomials 4670 int dU = deg(f2,vY); 4671 int dPY = deg(py, vY); 4672 4673 // Maximum integrality exponent 4674 int maxExpDen = (slN * (((d-1)-dU) div dPY)) div slD; 4675 if(dbg >= 1) 4676 { 4677 "Hensel lifting - order = ", maxExpDen; 4678 } 4679 // We compute the lifiting of the factor outside the origin up to the 4680 // maximum integrality exponent 4681 list hen = henselGlobal(f1, f2, fOrig, maxExpDen); 4682 poly p = hen[1]; 4683 poly u = hen[2]; 4684 4685 // We multiply the conjugates of (y - PE) to get a polynomial over 4686 // the ground field 4687 poly PEGround = buildPolyFrac(PE); 4688 //"PE: "; PE; 4689 //"PEground: "; PEGround; 4690 4691 // We compute the integral basis from the data obtained. 4692 // It will be a product of u (the factor outside the singularity) and 4693 // powers of y and PEGround. 4694 int expDen; 4695 int expPY, expY; // The exponent of py and y in the numerator. 4696 int ordU; 4697 if(locBasis == 0) 4698 { 4699 for(i = 0; i < d; i++){ 4700 if(i >= dU + dPY){ 4701 expDen = (slN * ((i-dU) div dPY)) div slD; 4702 ordU = expDen - 1; 4703 if (ordU < 0){ordU = 0;} 4704 expPY = (int(i-dU) div dPY); 4705 expY = i-dU-(expPY * dPY); 4706 ib[i+1] = list(PEGround^expPY * y^expY, x^(expDen)); 4707 if(dU > 0){ 4708 ib[i+1][1] = ib[i+1][1] * jet(u, ordU, vX); 4709 } 4710 } else { 4711 ib[i+1] = list(y^i, 1); 4712 } 4713 } 4714 } else 4715 { 4716 for(i = 0; i < d - dU; i++) 4717 { 4718 if(i > 0) 4719 { 4720 expDen = (slN* (i div dPY)) div slD; 4721 expPY = (i/dPY); 4722 expY = i-(expPY * dPY); 4723 ib[i+1] = list(py^expPY * y^expY, x^(expDen)); 4724 } else 4725 { 4726 ib[1] = list(1, 0); 4727 } 4728 } 4729 } 4730 4731 // We put the integral basis in the usual form, with a common denominator. 4732 poly den = ib[size(ib)][2]; 4733 ideal ibCom; 4734 for(i = 1; i<= size(ib); i++){ 4735 ibCom[i] = ib[i][1]*den/ib[i][2]; 4736 } 4737 list new = list(ibCom, den); 4738 //"time for generating the base: "; timer - t; 4739 return(new); 4740 } 4741 4742 // Checks if two lists are equal 4743 static proc equalLists(list l1, list l2) 4744 { 4745 int i; 4746 if(size(l1) != size(l2)) 4747 { 4748 return(0); 4749 } 4750 for(i = 1; i <= size(l1); i++) 4751 { 4752 if(l1[i] != l2[i]) 4753 { 4754 return(0); 4755 } 4756 } 4757 return(1); 4758 } 4759 4760 4761 // Merge classes if the corresponding factors are not over the ground field 4762 // Takes as input the output of proc irreducibleFactors 4763 4764 static proc mergeClassesIF(poly f, list classes, list ifOut, int mdm) 4765 { 4766 int h, i, j; 4767 4768 list cl; 4769 4770 int rep = 0; 4771 4772 for(i = 1; i <= size(classes); i++) 4773 { 4774 if(ifOut[2][i+1] == 0) 4775 { 4776 "Recombination of conjugation classes is not fully implemented. "; 4777 "Please check output."; 4778 4779 rep = 1; 4780 4781 cl = getClassVector(classes[i]); 4782 for(h = 1; h <= size(classes); h++) 4783 { 4784 if(i != h) 4785 { 4786 if(sameClass(cl, getClassVector(classes[h]), 1)) 4787 { 4788 classes[h] = setClassVector(classes[h], cl); 4789 } 4790 } 4791 } 4792 break; 4793 } 4794 } 4795 4796 // Regroup classes 4797 list classesNew; 4798 for(i = 1; i <= size(classes); i++) 4799 { 4800 classesNew = classesNew + classes[i]; 4801 } 4802 classes = getClasses(classesNew); 4803 4804 if(rep == 1) 4805 { 4806 ifOut = irreducibleFactors(f, classes, mdm); 4807 if(ifOut[3] == 0) 4808 { 4809 classes = mergeClassesIF(f, classes, ifOut, mdm); 4810 } 4811 } 4812 return(list(classes, ifOut)); 4813 } 4814 4815 static proc mergeTwoClasses(list classes, int a1, int a2) 4816 { 4817 classes[a1] = classes[a1] + classes[a2]; 4818 classes = delete(classes,a2); 4819 return(classes); 4820 } 4821 4822 4823 ///////////////////////////////////////////////////////////////////// 4824 4825 // splitring from primitiv.lib changed so that the variables 4826 // are named @a and not a 4827 4828 static proc splitRingAt(poly f,list #) 4829 "USAGE: splitringAt(f[,L]); f poly, L list of polys and/or ideals 4830 (optional) 4831 ASSUME: f is univariate and irreducible over the active ring. @* 4832 The active ring must allow an algebraic extension (e.g., it cannot 4833 be a transcendent ring extension of Q or Z/p). 4834 RETURN: ring; @* 4835 if called with a nonempty second parameter L, then in the output 4836 ring there is defined a list erg ( =L mapped to the new ring); 4837 if the minpoly of the active ring is non-zero, then the image of 4838 the primitive root of f in the output ring is appended as last 4839 entry of the list erg. 4840 NOTE: If the old ring has no parameter, the name @code{a} is chosen for the 4841 parameter of R (if @code{a} is no ring variable; if it is, @code{b} is 4842 chosen, etc.; if @code{a,b,c,o} are ring variables, 4843 @code{splitring(f[,L])} produces an error message), otherwise the 4844 name of the parameter is kept and only the minimal polynomial is 4845 changed. @* 4846 The names of the ring variables and the orderings are not affected. @* 4847 KEYWORDS: algebraic field extension; extension of rings 4848 EXAMPLE: example splitring; shows an example 4849 " 4850 { 4851 //----------------- split ist bereits eine proc in 'inout.lib' ! ------------- 4852 if (size(#)>=1) { 4853 list L=#; 4854 int L_groesse=size(L); 4855 } 4856 else { int L_groesse=-1; } 4857 //-------------- ermittle das Minimalpolynom des aktuellen Rings: ------------ 4858 string minp=string(minpoly); 4859 4860 def altring=basering; 4861 string charakt=string(char(altring)); 4862 string varnames=varstr(altring); 4863 string algname; 4864 int i; 4865 int anzvar=size(maxideal(1)); 4866 //--------------- Fall 1: Bisheriger Ring hatte kein Minimalpolynom ---------- 4867 if (minp=="0") { // only possible without parameters (by assumption) 4868 if (find(varnames,"@a")==0) { algname="@a";} 4869 else { if (find(varnames,"@b")==0) { algname="@b";} 4870 else { if (find(varnames,"@c")==0) 4871 { algname="@c";} 4872 else { if (find(varnames,"@o")==0) 4873 { algname="@o";} 4874 else { 4875 "** Sorry -- could not find a free name for the primitive element."; 4876 "** Try e.g. a ring without '@a' or '@b' as variable."; 4877 return(); 4878 }} 4879 } 4880 } 4881 //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: - 4882 execute("ring splt1="+charakt+","+algname+",dp;"); 4883 ideal abbnach=var(1); 4884 for (i=1; i<anzvar; i++) { abbnach=abbnach,var(1); } 4885 map nach_splt1=altring,abbnach; 4886 execute("poly mipol="+string(nach_splt1(f))+";"); 4887 string Rminp=string(mipol); 4888 //~; 4889 4890 //--------------------- definiere den neuen Ring: --------------------------- 4891 list ordStrNew = ordstr(altring); 4892 int jj = attrib(altring,"maxExp"); 4893 4894 ordStrNew = ordStrNew + list("L", jj); 4895 4896 execute("ring neuring = ("+charakt+","+algname+"),("+varnames+"),(" 4897 +ordstr(altring)+");"); 4898 execute("minpoly="+Rminp+";"); 4899 4900 //---------------------- Berechne die zurueckzugebende Liste: --------------- 4901 if (L_groesse>0) { 4902 list erg; 4903 map take=altring,maxideal(1); 4904 erg=take(L); 4905 } 4906 } 4907 else { 4908 4909 //------------- Fall 2: Bisheriger Ring hatte ein Minimalpolynom: ----------- 4910 algname=parstr(altring); // Name des algebraischen Elements 4911 if (npars(altring)>1) {"only one Parameter is allowed!!"; return(altring);} 4912 4913 //---------------- Minimalpolynom in ein Polynom umwandeln: ----------------- 4914 execute("ring splt2="+charakt+","+algname+",dp;"); 4915 execute("poly mipol="+minp+";"); 4916 // f ist Polynom in algname und einer weiteren Variablen -> mache f bivariat: 4917 execute("ring splt3="+charakt+",("+algname+","+varnames+"),dp;"); 4918 poly f=imap(altring,f); 4919 4920 //-------------- Vorbereitung des Aufrufes von primitive: ------------------- 4921 execute("ring splt1="+charakt+",(x,y),dp;"); 4922 ideal abbnach=x; 4923 for (i=1; i<=anzvar; i++) { abbnach=abbnach,y; } 4924 map nach_splt1_3=splt3,abbnach; 4925 map nach_splt1_2=splt2,x; 4926 ideal maxid=nach_splt1_2(mipol),nach_splt1_3(f); 4927 ideal primit=primitive(maxid); 4928 if (size(primit)==0) { // Suche mit 1. Proc erfolglos 4929 primit=primitive_extra(maxid); 4930 } 4931 //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: - 4932 setring splt2; 4933 map nach_splt2=splt1,0,var(1); // x->0, y->a 4934 minp=string(nach_splt2(primit)[1]); 4935 if (printlevel > -1) { "// new minimal polynomial:",minp; } 4936 //--------------------- definiere den neuen Ring: --------------------------- 4937 execute("ring neuring = ("+charakt+","+algname+"),("+varnames+"),(" 4938 +ordstr(altring)+");"); 4939 execute("minpoly="+minp+";"); 4940 4941 if (L_groesse>0) { 4942 //---------------------- Berechne die zurueckzugebende Liste: ------------- 4943 list erg; 4944 setring splt3; 4945 list zwi=imap(altring,L); 4946 map nach_splt3_1=splt1,0,var(1); // x->0, y->a 4947 //----- rechne das primitive Element von altring in das von neuring um: --- 4948 ideal convid=maxideal(1); 4949 convid[1]=nach_splt3_1(primit)[2]; 4950 poly new_b=nach_splt3_1(primit)[3]; 4951 map convert=splt3,convid; 4952 zwi=convert(zwi); 4953 setring neuring; 4954 erg=imap(splt3,zwi); 4955 erg[size(erg)+1]=imap(splt3,new_b); 4956 } 4957 } 4958 if (defined(erg)){export erg;} 4959 return(neuring); 4960 } 4961 example 4962 { "EXAMPLE:"; echo = 2; 4963 ring r=0,(x,y),dp; 4964 def r1=splitring(x2-2); 4965 setring r1; basering; // change to Q(sqrt(2)) 4966 // change to Q(sqrt(2),sqrt(sqrt(2)))=Q(a) and return the transformed 4967 // old parameter: 4968 def r2=splitring(x2-a,a); 4969 setring r2; basering; erg; 4970 // the result is (a)^2 = (sqrt(sqrt(2)))^2 4971 kill r1; kill r2; 4972 } 426 4973 /////////////////////////////////////////////////////////////////////////////// 427 4974 428 static proc cancelCF(list IB) 429 "USAGE: cancelCF(IB); IB list of type returned by integralBasis 430 RETURN: list of same type with common factor cancelled. 431 KEYWORDS: greatest common divisor. 4975 4976 static proc getClassVector(list cl); 4977 { 4978 if(typeof(cl[1]) == "ring") 4979 { 4980 def S = cl[1]; 4981 setring S; 4982 list clVec = PE[1][6]; 4983 } else 4984 { 4985 list clVec = cl[1][6]; 4986 } 4987 return(clVec); 4988 } 4989 4990 static proc setClassVector(list cl, list clVec); 4991 { 4992 def R = basering; 4993 int i, j; 4994 for(i = 1; i <=size(cl); i++) 4995 { 4996 if(typeof(cl[i]) == "ring") 4997 { 4998 def S = cl[i]; 4999 setring S; 5000 for(j = 1; j <= size(PE); j++) 5001 { 5002 PE[j][6] = clVec; 5003 } 5004 setring R; 5005 kill S; 5006 } else 5007 { 5008 for(j = 1; j <= size(cl); j++) 5009 { 5010 cl[j][6] = clVec; 5011 } 5012 5013 } 5014 } 5015 return(cl); 5016 } 5017 5018 static proc sameClass(list l1, list l2, int offset) 5019 { 5020 int i; 5021 int same = 1; 5022 for(i = 1; i <= size(l1) - offset; i++) 5023 { 5024 if(l1[i] != l2[i]) 5025 { 5026 same = 0; 5027 } 5028 } 5029 return(same); 5030 } 5031 5032 5033 // proc checkClass(list expClass) 5034 // { 5035 // // If there is only one expansion in the class, there is nothing to do 5036 // if(typeof(expClass[1]) == "ring") 5037 // { 5038 // for(j = 1; j <= size(classes[i]); j++) 5039 // { 5040 // if(typeof(classes[i][j]) == "ring") 5041 // { 5042 // S = classes[i][j]; 5043 // setring S; 5044 // if(typeof(PE[1][7])!= "none") 5045 // { 5046 // 5047 5048 /////////////////////////////////////////////////////////////////////////////// 5049 // Copied from classify.lib 5050 static proc init_debug_intbas(list #) 5051 "USAGE: init_debug([level]); level=int 5052 COMPUTE: Set the global variable @DeBug to level. The variable @DeBug is 5053 used by the function debug_log_intbas(level, list of strings) to know 5054 when to print the list of strings. init_debug() reports only 5055 changes of @DeBug. 5056 NOTE: The procedure init_debug(n); is usefull as trace-mode. n may 5057 range from 0 to 10, higher values of n give more information. 5058 EXAMPLE: example init_debug; shows an example" 5059 { 5060 int newDebug=0; 5061 if( defined(@DeBug) != 0 ) { newDebug = @DeBug; } 5062 5063 if( size(#) > 0 ) 5064 { 5065 newDebug=#[1]; 5066 } 5067 else 5068 { 5069 string s=system("getenv", "SG_DEBUG"); 5070 if( s != "" && defined(@DeBug)==0) 5071 { 5072 s="newDebug="+s; 5073 execute(s); 5074 } 5075 } 5076 if( defined(@DeBug) == 0) 5077 { 5078 int @DeBug = newDebug; 5079 export @DeBug; 5080 if(@DeBug>0) { "Debugging level is set to ", @DeBug; } 5081 } 5082 else 5083 { 5084 if( (size(#) == 0) && (newDebug < @DeBug) ) { return(); } 5085 if( @DeBug != newDebug) 5086 { 5087 int oldDebug = @DeBug; 5088 @DeBug = newDebug; 5089 if(@DeBug>0) { "Debugging level change from ", oldDebug, " to ",@DeBug; } 5090 else 5091 { 5092 if( @DeBug==0 && oldDebug>0 ) { "Debugging switched off."; } 5093 } 5094 } 5095 } 5096 //printlevel = @DeBug; 5097 } 5098 example 5099 { "EXAMPLE:"; echo=2; 5100 init_debug(); 5101 debug_log_intbas(1,"no trace information printed"); 5102 init_debug(1); 5103 debug_log_intbas(1,"some trace information"); 5104 init_debug(2); 5105 debug_log_intbas(2,"nice for debugging scripts"); 5106 init_debug(0); 5107 } 5108 5109 /////////////////////////////////////////////////////////////////////////////// 5110 static proc debug_log_intbas (int level, list #) 5111 "USAGE: debug_log_intbas(level,li); level=int, li=comma separated \"message\" list 5112 COMPUTE: print \"messages\" if level>=@DeBug. 5113 useful for user-defined trace messages. 5114 EXAMPLE: example debug_log_intbas; shows an example 5115 SEE ALSO: init_debug 432 5116 " 433 5117 { 434 int l = size(IB[1]); 435 poly GrCoDi = IB[2]; 436 int k = l; 437 while((GrCoDi != 1) && (k >=1)) 438 { 439 GrCoDi = gcd(GrCoDi,IB[1][k]); 440 k = k-1; 441 } 442 if(GrCoDi != 1) 443 { 444 for(k = 1; k <= l; k++) 445 { 446 IB[1][k] = IB[1][k]/GrCoDi; 447 } 448 IB[2] = IB[2]/GrCoDi; 449 } 450 return(IB); 451 } 5118 int len = size(#); 5119 // int printresult = printlevel - level +1; 5120 // if(level>1) 5121 // { 5122 // dbprint(printresult, "Debug:("+ string(level)+ "): ", #[2..len]); 5123 // } 5124 // else { dbprint(printresult, #[1..len]); } 5125 if( defined(@DeBug) == 0 ) { init_debug_intbas(); } 5126 if(@DeBug>=level) 5127 { 5128 if(level>1) { "Debug:("+ string(level)+ "): ", #[1..len]; } 5129 else { #[1..len]; } 5130 } 5131 } 5132 example 5133 { "EXAMPLE:"; echo=2; 5134 example init_debug; 5135 } 5136 5137 static proc debug_lvl() 5138 { 5139 int j = @DeBug; 5140 return(j); 5141 } 5142 5143 // Alternative procedure for computing characteristic exponents 5144 // from the exponentes of the series. 5145 // Not used beacuse we need to use characteristic orders, it is 5146 // not enough to compute the characteristic exponents. 5147 static proc charExp(intvec v, int k) 5148 { 5149 intvec vNew; 5150 int i = 1; 5151 int ind = 1; 5152 while ((v[i] mod k) == 0) 5153 { 5154 i++; 5155 } 5156 vNew[1] = v[i]; 5157 ind++; 5158 int g = gcd(k, vNew[1]); 5159 while(i <= size(v)) 5160 { 5161 while((v[i] mod g) == 0) 5162 { 5163 i++; 5164 if(i > size(v)){break;} 5165 } 5166 if(i <= size(v)) 5167 { 5168 vNew[ind] = v[i]; 5169 g = gcd(g, vNew[ind]); 5170 ind++; 5171 } 5172 } 5173 return(vNew); 5174 } 5175 5176 5177 452 5178 ///////////////////////////////////////////////////////////////////////////// 453 5179 ///////////////////////////////////////////////////////////////////////////// … … 487 5213 integralBasis(f, 2); 488 5214 f =1/11*f; 5215 integralBasis(f, 2); // local by default, time 0 489 5216 integralBasis(f, 2, "global"); // time 2 490 integralBasis(f, 2); // local by default, time 0491 5217 kill RR; 492 5218 // ------------------------------------------------------- … … 507 5233 ring RR = 0, (x,y), dp; 508 5234 poly f = fetch(SS,f); 509 integralBasis(f, 2); integralBasis(f, 2, "global"); // time 1510 5235 integralBasis(f, 2); // local by default, time 0 5236 integralBasis(f, 2, "global"); // time 1 511 5237 kill RR, SS; 512 5238 // ------------------------------------------------------- … … 567 5293 kill RR, SS; 568 5294 */ 569 570 -
Tst/Manual/integralBasis.res.gz.uu
r1edfd9 r7d6fbd 1 1 begin 640 integralBasis.res.gz 2 M'XL(",0I<DX``VEN=&5G<F%L0F%S:7,N<F5S`'52RV[",!"\YRM6J(<@0B#! 3 M]!7A`^H%"55"X8802HBAEAP'Q0Z-_[[KD$=[Z,FSN[/CV;7C_<?F$P`""MO- 4 M&D9::5_P=!0!HA.77+OCR+$G4`I<:G8M$[%.%%>^9-^^THEVXE8D;$4Z6MK0 5 M&KF>LZ!P*Y$@V)T)6/T*)L'`(A0P?P6%C+GGUIX9>]EMJ"]1I1`&+E@WRZDA 6 M]828L`ZG-1E(SQ0$5QKL-7^<NQ</0AQK_\5`5GG*2B@N<"[R6R&9U,I&&FLQ 7 M6JA$4L*V.%<*N,(]]>HOJ!XYA^#X[F!T0K"J%P\86F@>>($X-.$C(!B8EK0\ 8 MK@R9$"PZV-"(8'^G_DIA-@-KL',.S38[:WWV+`I5E<SF=X?ZB`78-?O">20V 9 M:-5KOOE6LQ5@@N7=K`+-0\;O/&,9I*:IV_7*(N=XA4!_?J<2S/W_'G`Z/&"` 10 6_\E^(/L]*N4&X^C)^0$NE;9J:P(````` 2 M'XL(")KPP6$"`VEN=&5G<F%L0F%S:7,N<F5S`(53P4[C,!"]^RM&:`^IVAB2 3 MINPN57-@N51"2!7L"57(3=S6DF-7L0/QWS-V0DJTBSAE/._-FS?.^/'I;OT` 4 M`$D.]^M;N+#&4BEV%TO`Z$4H8:/)DO@OY#D(9?FA9O*6&6&HXF_46&;)8R^2 5 M]B(?M%V@!;F!,\_A5"-!\E<N8?7I,$W.K"P'S!_`(.-J%K4S-YF5IS.^0!4M 6 M'>P1=XO89>TT<VF;QFUV)EWG((6QX-N,G$?[&:0XUA]=G1KK^]@C'RC0V::4 7 MQ/&8P8S1A6"6E]YVQ0WH?0`,,AK):I"Z:$(I0/379T%I%5>Z#"B3!UT+>ZSH 8 MY!_M<7=@%C@KCE`@22NN;.?GFRJT,Q0`28:"D+@!$L#G9+MR?9AN5RU9CT6* 9 MT(%9H17L\<^;(R_I<*D_\5*7!#5N<$9X\6+MO`N]V-QU\1SCU*7=(<.#ZTD+ 10 M;)Y-,P0)%@01K/]0_Y7#Y24\_7>RT;R%U*:IN<]OGMLM`K`):X+V%198,VC^ 11 MIEZS%^"25W@705"B>2C%JRCQA^Y<P/U6*5T);"'1WS!W<D6_VMOXO+<)/B/_ 12 3;ORK:$R43)8_R#LE93,Z8@,````` 11 13 ` 12 14 end -
Tst/Manual/integralBasis.stat
r1edfd9 r7d6fbd 1 1 >> tst_memory_0 :: 1 316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:3854362 1 >> tst_memory_1 :: 1 316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:9625603 1 >> tst_memory_2 :: 1 316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:10238764 1 >> tst_timer_1 :: 1 316104113:3132- exportiert :3-1-3:ix86-Linux:mamawutz:321 1 >> tst_memory_0 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:486208 2 1 >> tst_memory_1 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:2482176 3 1 >> tst_memory_2 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:2650112 4 1 >> tst_timer_1 :: 1640099994:4212, 64 bit:4.2.1:x86_64-Linux:nepomuck:12 -
doc/NEWS.texi
r1edfd9 r7d6fbd 34 34 @item sagbigrob.lib: Sagbi-Groebner basis of an ideal of a subalgebra (@nref{sagbigrob_lib}) 35 35 @item puiseuxexpansion.lib: Puiseux expansions over algebraic extensions (@nref{puiseuxexpansioni_lib}) 36 @item integralbasis_lib: Integral basis in algebraic function fields: new version (@nref{integralbasis_lib}) 36 37 @end itemize 37 38
Note: See TracChangeset
for help on using the changeset viewer.