Changeset d2ea299 in git for Singular/LIB/normal.lib
- Timestamp:
- Sep 30, 2010, 2:58:22 PM (14 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- 29c1363a5cc3f5aba4a1805eaa27635901879349
- Parents:
- 57c64fff6c32591cb762f2f499785bea07c93048
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/LIB/normal.lib
r57c64ff rd2ea299 10 10 11 11 MAIN PROCEDURES: 12 normal(I [...]);normalization of an affine ring12 normal(I,[...]); normalization of an affine ring 13 13 normalP(I,[...]); normalization of an affine ring in positive characteristic 14 14 normalC(I,[...]); normalization of an affine ring through a chain of rings … … 16 16 genus(I); computes the geometric genus of a projective curve 17 17 primeClosure(L); integral closure of R/p, p a prime ideal 18 closureFrac(L); write a polynomialin integral closure as element of Quot(R/p)18 closureFrac(L); writes a poly in integral closure as element of Quot(R/p) 19 19 iMult(L); intersection multiplicity of the ideals of the list L 20 20 … … 23 23 locAtZero(I); checks whether the zero set of I is located at 0 24 24 norTest(I,nor); checks the output of normal, normalP, normalC 25 getSmallest(J); computes the polynomial of smallest degree of J 26 getOneVar(J, vari); computes a polynomial of J in the variable vari 27 changeDenominator(U1, c1, c2, I); computes ideal U2 such that 1/c1*U1=1/c2*U2 25 28 "; 26 29 … … 37 40 LIB "algebra.lib"; 38 41 39 40 42 /////////////////////////////////////////////////////////////////////////////// 41 43 42 44 proc normal(ideal id, list #) 43 "USAGE: normal(id [,choose]); id = radical ideal, choose = list of optional 44 strings. @* 45 "USAGE: normal(id [,choose]); id = radical ideal, choose = list of options. @* 45 46 Optional parameters in list choose (can be entered in any order):@* 46 47 Decomposition:@* … … 65 66 If the optional parameter choose is not given or empty, only 66 67 \"equidim\" but no other option is used.@* 67 The following options can be used when the ring has two variables. 68 They are needed for computing integral basis.@* 69 - \"var1\" -> uses a polynomial in the first variable as conductor.@* 70 - \"var2\" -> uses a polynomial in the second variable as conductor.@* 68 - list(\"inputJ\", ideal inputJ) -> takes as initial test ideal the 69 ideal inputJ. This option is only for use in other procedures. Using 70 this option, the result might not be the normalization.@* 71 (Option only valid for global algorithm.)@* 72 - list(\"inputC\", ideal inputC) -> takes as initial conductor the 73 ideal inputC. This option is only for use in other procedures. Using 74 this option, the result might not be the normalization.@* 75 (Option only valid for global algorithm.)@* 76 Options used for computing integral basis (over rings of two 77 variables):@* 78 - \"var1\" -> uses a polynomial in the first variable as 79 universal denominator.@* 80 - \"var2\" -> uses a polynomial in the second variable as universal 81 denominator.@* 82 If the optional parameter choose is not given or empty, only 83 \"equidim\" but no other option is used.@* 71 84 ASSUME: The ideal must be radical, for non-radical ideals the output may 72 85 be wrong (id=radical(id); makes id radical). However, when using the … … 142 155 int nvar = nvars(basering); 143 156 int chara = char(basering); 144 int conduOption; // Method for choosing the conductor 157 int denomOption; // Method for choosing the conductor 158 159 ideal inputJ = 0; // Test ideal given in the input (if any). 160 ideal inputC = 0; // Conductor ideal given in the input (if any). 161 145 162 list result, resultNew; 146 163 list keepresult; … … 156 173 // computations there. 157 174 withDelta = 0; // Do not compute the delta invariant. 175 denomOption = 0; // The default universal denominator is the smallest 176 // degree polynomial. 158 177 159 178 //--------------------------- define the method --------------------------- 160 string method; //make all options one string in order to use161 //all combinations of options simultaneously162 179 for ( i=1; i <= size(#); i++ ) 163 180 { 164 181 if ( typeof(#[i]) == "string" ) 165 182 { 166 method = method + #[i];167 }168 }169 170 183 //--------------------------- choosen methods ----------------------- 171 if ( find(method,"isprim") or find(method,"isPrim") ) 172 {decomp = 0;} 173 174 if ( find(method,"nodeco") or find(method,"noDeco") ) 175 {decomp = 1;} 176 177 if ( find(method,"prim") ) 178 {decomp = 3;} 179 180 if ( find(method,"equidim") ) 181 {decomp = 2;} 182 183 if ( find(method,"nofac") or find(method,"noFac") ) 184 {noFac=1;} 185 186 if ( (find(method,"useRing") or find(method,"usering")) and (ordstr(basering) != "dp("+string(nvars(basering))+"),C")) 187 {useRing = 1;} 188 189 if ( find(method,"withDelta") or find(method,"wd") or find(method,"withdelta")) 190 { 191 if((decomp == 0) or (decomp == 3)) 192 { 193 withDelta = 1; 194 } 195 else 196 { 197 decomp = 3; 198 withDelta = 1; 199 //Note: the delta invariants cannot be computed with an equidimensional 200 //decomposition, hence we compute first the minimal primes 201 } 202 } 203 204 conduOption = 0; // The default is the smallest degree polynomial 205 if ( find(method,"var1") ) 206 {conduOption = 1;} 207 if ( find(method,"var2") ) 208 {conduOption = 2;} 209 210 184 if ( (#[i]=="isprim") or (#[i]=="isPrim") ) 185 {decomp = 0;} 186 187 if ( (#[i]=="nodeco") or (#[i]=="noDeco") ) 188 {decomp = 1;} 189 190 if (#[i]=="prim") 191 {decomp = 3;} 192 193 if (#[i]=="equidim") 194 {decomp = 2;} 195 196 if ( (#[i]=="nofac") or (#[i]=="noFac") ) 197 {noFac=1;} 198 199 if ( ((#[i]=="useRing") or (#[i]=="usering")) and (ordstr(basering) != "dp("+string(nvars(basering))+"),C")) 200 {useRing = 1;} 201 202 if ( (#[i]=="withDelta") or (#[i]=="wd") or (#[i]=="withdelta")) 203 { 204 if((decomp == 0) or (decomp == 3)) 205 { 206 withDelta = 1; 207 } 208 else 209 { 210 decomp = 3; 211 withDelta = 1; 212 //Note: the delta invariants cannot be computed with an equidimensional 213 //decomposition, hence we compute first the minimal primes 214 } 215 } 216 if (#[i]=="var1") 217 {denomOption = 1;} 218 if (#[i]=="var2") 219 {denomOption = 2;} 220 } 221 if(typeof(#[i]) == "list"){ 222 if(size(#[i]) == 2){ 223 if (#[i][1]=="inputJ"){ 224 if(typeof(#[i][2]) == "ideal"){ 225 inputJ = #[i][2]; 226 } 227 } 228 } 229 if (#[i][1]=="inputC"){ 230 if(size(#[i]) == 2){ 231 if(typeof(#[i][2]) == "ideal"){ 232 inputC = #[i][2]; 233 } 234 } 235 } 236 } 237 } 211 238 kill #; 212 list #;213 239 214 240 //------------------------ change ring if required ------------------------ … … 307 333 { 308 334 def R = basering; 335 ideal inputJ = fetch(origR, inputJ); 336 ideal inputC = fetch(origR, inputC); 309 337 if(useRing == 0) 310 338 { … … 344 372 } 345 373 printlevel = printlevel + 1; 346 norComp = normalM(prim[i], decomp, withDelta, conduOption);374 norComp = normalM(prim[i], decomp, withDelta, denomOption, inputJ, inputC); 347 375 printlevel = printlevel - 1; 348 376 for(j = 1; j <= size(norComp); j++) … … 1403 1431 "// extra test for onlySingularAtZero:"; 1404 1432 } 1405 if ( locAtZero(JM[1]) ) 1406 { 1407 attrib(SM[2],"onlySingularAtZero",1); 1408 JM = maxideal(1),maxideal(1); 1409 attrib(JM[1],"isSB",1); 1410 attrib(JM[2],"isRadical",1); 1411 } 1412 else 1413 { 1433 // Not so cheap... removed 1434 //if ( locAtZero(JM[1]) ) 1435 //{ 1436 // attrib(SM[2],"onlySingularAtZero",1); 1437 // JM = maxideal(1),maxideal(1); 1438 // attrib(JM[1],"isSB",1); 1439 // attrib(JM[2],"isRadical",1); 1440 //} 1441 //else 1442 //{ 1414 1443 attrib(SM[2],"onlySingularAtZero",0); 1415 }1444 //} 1416 1445 } 1417 1446 … … 2550 2579 " 2551 2580 { 2552 intvec save_opt=option(get);2553 2581 option(redSB); 2554 2582 def R=basering; … … 2634 2662 } 2635 2663 } 2636 option( set,save_opt);2664 option(noredSB); 2637 2665 ideal fstd=std(ideal(f)+jacob(f)); 2638 2666 poly hc=highcorner(fstd); … … 4179 4207 // From here: subprocedures for normal 4180 4208 4181 static proc normalM(ideal I, int decomp, int withDelta, int conduOption){ 4209 // inputJ is used in parametrization of rational curves algorithms, to specify 4210 // a different test ideal. 4211 4212 static proc normalM(ideal I, int decomp, int withDelta, int denomOption, ideal inputJ, ideal inputC){ 4182 4213 // Computes the normalization of a ring R / I using the module structure as far 4183 4214 // as possible. … … 4200 4231 // ring, contained in the radical of the singular locus. 4201 4232 // This denominator is used except when the degree of D^i is greater than the 4202 // degree of a conductor.4233 // degree of a universal denominator. 4203 4234 // The nzd is taken as the smallest degree polynomial in the radical of the 4204 4235 // singular locus. … … 4217 4248 // decomp = 3 (meaning that the ideal is prime). 4218 4249 4219 // conduOption = 0 -> Uses the smallest degree polynomial4220 // conduOption = i > 0 -> Uses a polynomial in the i-th variable4250 // denomOption = 0 -> Uses the smallest degree polynomial 4251 // denomOption = i > 0 -> Uses a polynomial in the i-th variable 4221 4252 4222 4253 option("redSB"); … … 4252 4283 option("redSB"); 4253 4284 option("returnSB"); 4254 ideal I = fetch(R, I); 4255 attrib(I, "isSB", 1); 4256 ideal IMin = fetch(R, IMin); 4257 4258 dbprint(dbg, "Computing the jacobian ideal..."); 4259 4260 ideal J = minor(jacob(IMin), nvars(basering) - d, I); 4261 J = groebner(J); 4285 4286 // If a conductor ideal was given as input, we use it instead of the 4287 // singular locus. If a test ideal was given as input, we do not compute the 4288 // singular locus. 4289 ideal inputC = fetch(R, inputC); 4290 ideal inputJ = fetch(R, inputJ); 4291 if((inputC == 0) && (inputJ == 0)){ 4292 // We compute the radical of the ideal of minors modulo the original ideal. 4293 // This is done only in the first step. 4294 ideal I = fetch(R, I); 4295 attrib(I, "isSB", 1); 4296 ideal IMin = fetch(R, IMin); 4297 4298 dbprint(dbg, "Computing the jacobian ideal..."); 4299 4300 // If a given conductor ideal is given, we use it. 4301 // If a given test ideal is given, we don't need to compute the jacobian 4302 ideal J = minor(jacob(IMin), nvars(basering) - d, I); 4303 J = groebner(J); 4304 } else { 4305 ideal J = fetch(R, inputC); 4306 J = groebner(J); 4307 } 4262 4308 4263 4309 //------------------ We check if the singular locus is empty ------------- … … 4285 4331 4286 4332 4287 // -------------------- election of the conductor ------------------------- 4288 if(conduOption == 0){ 4289 poly condu = getSmallest(J); // Choses the polynomial of smallest degree 4290 // of J as universal denominator. 4291 } 4292 else 4293 { 4294 poly condu = getOnevar(J, conduOption); 4295 } 4296 if(dbg >= 1){ 4297 ""; 4298 "The universal denominator is ", condu; 4299 } 4300 4301 // --------- splitting the ideal by the conductor (if possible) ----------- 4302 // If the ideal is equidimensional, but not necessarily prime, we check if 4303 // the conductor is a non-zerodivisor of R/I. 4304 // If not, we split I. 4305 if((decomp == 1) or (decomp == 2)){ 4306 ideal Id1 = quotient(0, condu); 4307 if(size(Id1) > 0){ 4308 // We have to split. 4309 if(dbg >= 1){ 4310 "A zerodivisor was found. We split the ideal. The zerodivisor is ", condu; 4311 } 4312 setring R; 4313 ideal Id1 = fetch(Q, Id1), I; 4314 Id1 = groebner(Id1); 4315 ideal Id2 = quotient(I, Id1); 4316 // I = I1 \cap I2 4317 printlevel = printlevel + 1; 4318 list nor1 = normalM(Id1, decomp, withDelta, conduOption)[1]; 4319 list nor2 = normalM(Id2, decomp, withDelta, conduOption)[1]; 4320 printlevel = printlevel - 1; 4321 return(list(nor1, nor2)); 4322 } 4333 // -------------------- election of the universal denominator---------------- 4334 // We first check if a conductor ideal was computed. If not, we don't 4335 // compute a universal denominator. 4336 ideal Id1; 4337 if(J != 0){ 4338 if(denomOption == 0){ 4339 poly condu = getSmallest(J); // Choses the polynomial of smallest degree 4340 // of J as universal denominator. 4341 } else { 4342 poly condu = getOneVar(J, denomOption); 4343 } 4344 if(dbg >= 1){ 4345 ""; 4346 "The universal denominator is ", condu; 4347 } 4348 4349 // ----- splitting the ideal by the universal denominator (if possible) ----- 4350 // If the ideal is equidimensional, but not necessarily prime, we check if 4351 // the universal denominator is a non-zerodivisor of R/I. 4352 // If not, we split I. 4353 if((decomp == 1) or (decomp == 2)){ 4354 Id1 = quotient(0, condu); 4355 if(size(Id1) > 0){ 4356 // We have to split. 4357 if(dbg >= 1){ 4358 "A zerodivisor was found. We split the ideal. The zerodivisor is ", condu; 4359 } 4360 setring R; 4361 ideal Id1 = fetch(Q, Id1), I; 4362 Id1 = groebner(Id1); 4363 ideal Id2 = quotient(I, Id1); 4364 // I = I1 \cap I2 4365 printlevel = printlevel + 1; 4366 ideal JDefault = 0; // Now it uses the default J; 4367 list nor1 = normalM(Id1, decomp, withDelta, denomOption, JDefault, JDefault)[1]; 4368 list nor2 = normalM(Id2, decomp, withDelta, denomOption, JDefault, JDefault)[1]; 4369 printlevel = printlevel - 1; 4370 return(list(nor1, nor2)); 4371 } 4372 } 4373 } else { 4374 poly condu = 0; 4323 4375 } 4324 4376 … … 4327 4379 // If we are using a non-global ordering, we must change to the global 4328 4380 // ordering. 4329 if(isGlobal == 1){ 4330 setring R; 4331 ideal J = fetch(Q, J); 4332 J = J, I; 4333 if(dbg >= 1){ 4334 "The original singular locus is"; 4335 groebner(J); 4336 if(dbg >= 2){pause();} 4337 ""; 4338 } 4339 // We check if the only singular point is the origin. 4340 // If so, the radical is the maximal ideal at the origin. 4341 J = groebner(J); 4342 if(locAtZero(J)){ 4343 J = maxideal(1); 4344 } 4345 else 4346 { 4381 setring R; 4382 // If a test ideal is given at the input, we use it. 4383 if(inputJ == 0){ 4384 if(isGlobal == 1){ 4385 ideal J = fetch(Q, J); 4386 J = J, I; 4387 if(dbg >= 1){ 4388 "The original singular locus is"; 4389 groebner(J); 4390 if(dbg >= 2){pause();} 4391 ""; 4392 } 4393 // We check if the only singular point is the origin. 4394 // If so, the radical is the maximal ideal at the origin. 4395 J = groebner(J); 4396 if(locAtZero(J)){ 4397 J = maxideal(1); 4398 } else { 4399 J = radical(J); 4400 } 4401 } else { 4402 // We change to global dp ordering. 4403 list rl = ringlist(R); 4404 list origOrd = rl[3]; 4405 list newOrd = list("dp", intvec(1:nvars(R))), list("C", 0); 4406 rl[3] = newOrd; 4407 def globR = ring(rl); 4408 setring globR; 4409 ideal J = fetch(Q, J); 4410 ideal I = fetch(R, I); 4411 J = J, I; 4412 if(dbg >= 1){ 4413 "The original singular locus is"; 4414 groebner(J); 4415 if(dbg>=2){pause();} 4416 ""; 4417 } 4347 4418 J = radical(J); 4348 } 4349 } 4350 else 4351 { 4352 // We change to global dp ordering. 4353 list rl = ringlist(R); 4354 list origOrd = rl[3]; 4355 list newOrd = list("dp", intvec(1:nvars(R))), list("C", 0); 4356 rl[3] = newOrd; 4357 def globR = ring(rl); 4358 setring globR; 4359 ideal J = fetch(Q, J); 4360 ideal I = fetch(R, I); 4361 J = J, I; 4362 if(dbg >= 1){ 4363 "The original singular locus is"; 4364 groebner(J); 4365 if(dbg>=2){pause();} 4366 ""; 4367 } 4368 J = radical(J); 4369 setring R; 4370 ideal J = fetch(globR, J); 4419 setring R; 4420 ideal J = fetch(globR, J); 4421 } 4422 } else { 4423 ideal J = inputJ; 4371 4424 } 4372 4425 … … 4381 4434 J = fetch(R, J); 4382 4435 J = interred(J); 4383 if( conduOption == 0){4436 if(denomOption == 0){ 4384 4437 poly D = getSmallest(J); // Chooses the polynomial of smallest degree as 4385 4438 // non-zerodivisor. 4386 } 4387 else 4388 { 4389 poly D = getOnevar(J, conduOption); 4439 } else { 4440 poly D = getOneVar(J, denomOption); 4390 4441 } 4391 4442 if(dbg >= 1){ … … 4414 4465 printlevel = printlevel + 1; 4415 4466 4416 list nor1 = normalM(Id1, decomp, withDelta, conduOption)[1]; 4417 list nor2 = normalM(Id2, decomp, withDelta, conduOption)[1]; 4467 ideal JDefault = 0; // Now it uses the default J; 4468 list nor1 = normalM(Id1, decomp, withDelta, denomOption, JDefault, JDefault)[1]; 4469 list nor2 = normalM(Id2, decomp, withDelta, denomOption, JDefault, JDefault)[1]; 4418 4470 printlevel = printlevel - 1; 4419 4471 return(list(nor1, nor2)); … … 4428 4480 J = fetch(Q, J); 4429 4481 printlevel = printlevel + 1; 4430 list result = normalMEqui(I, J, condu, D, withDelta, conduOption);4482 list result = normalMEqui(I, J, condu, D, withDelta, denomOption); 4431 4483 printlevel = printlevel - 1; 4432 4484 return(list(result)); … … 4442 4494 // origJ is the first test ideal. 4443 4495 // D is a non-zerodivisor of R/I. 4444 // condu is a non-zerodivisor in the conductor .4496 // condu is a non-zerodivisor in the conductor or 0 if it was not computed. 4445 4497 // If withDelta = 1, computes the delta invariant. 4446 4498 { … … 4567 4619 // The new denominator is chosen. 4568 4620 c = D * c; 4569 if(deg(c) > deg(condu)) 4570 { 4571 U = changeDenominatorQ(U, c, condu); 4572 c = condu; 4621 4622 // If we have a universal denominator of smaller degree than c, 4623 // we replace c by it. 4624 if(condu != 0){ 4625 if(deg(c) > deg(condu)) 4626 { 4627 U = changeDenominatorQ(U, c, condu); 4628 c = condu; 4629 } 4573 4630 } 4574 4631 if(dbg >= 1) … … 4651 4708 4652 4709 //WARNING - elim is not working here!! Check!! 4653 //It is now replace by computing an eliminating groebner basis. 4654 static proc getOnevar(ideal J, int vari) 4710 //It is now replaced by computing an eliminating groebner basis. 4711 proc getOneVar(ideal J, int vari) 4712 "USAGE: getOneVar(J, vari); J is a 0-dimensional ideal, vari is an integer. 4713 RETURN: a polynomial of J in the variable indicated by vari of smallest 4714 degree.@* 4715 NOTE: Works only over rings of two variables.@* 4716 It is intended mainly as an auxiliary procedure for computing 4717 integral bases. @* 4718 EXAMPLE: example getOneVar; shows an example 4719 " 4655 4720 { 4656 // Computes the polynomial of smallest degree of J.4657 // If there are more than one, it chooses the one with smallest number4658 // of monomials.4659 4721 def R = basering; 4660 4722 ring RR = 0, (var(3-vari), var(vari)), lp; 4661 4723 ideal J = imap(R, J); 4662 4724 J = groebner(J); 4663 poly D= J[1];4725 poly g = J[1]; 4664 4726 setring R; 4665 poly D = imap(RR, D);4666 return( D);4727 poly g = imap(RR, g); 4728 return(g); 4667 4729 } 4668 4730 example 4731 { "EXAMPLE:"; 4732 printlevel = printlevel+1; 4733 echo = 2; 4734 ring s = 0,(x,y),dp; 4735 ideal J = x3-y, y3; 4736 getOneVar(J, 1); 4737 4738 echo = 0; 4739 printlevel = printlevel-1; 4740 } 4669 4741 /////////////////////////////////////////////////////////////////////////////// 4670 4742 4671 static proc getSmallest(ideal J) 4743 proc getSmallest(ideal J) 4744 "USAGE: getSmallest(J); J is an ideal. 4745 RETURN: the generator of J of smallest degree. If there are more than one, it 4746 chooses the one with smallest number of monomials.@* 4747 NOTE: It looks only at the generator of J, not at all the polynomials in 4748 the ideal.@* 4749 It is intended maninly to compute a good universal denominator in the 4750 normalization algorithms.@* 4751 EXAMPLE: example getSmallest; shows an example 4752 " 4672 4753 { 4673 4754 // Computes the polynomial of smallest degree of J. 4674 // If there are more than one, it chooses the one with smallest number 4675 // of monomials. 4755 // 4676 4756 int i; 4677 4757 poly p = J[1]; … … 4701 4781 } 4702 4782 return(p); 4783 } 4784 example 4785 { "EXAMPLE:"; 4786 printlevel = printlevel+1; 4787 echo = 2; 4788 ring s = 0,(x,y),dp; 4789 ideal J = x3-y, y5, x2-y2+1; 4790 getSmallest(J); 4791 4792 echo = 0; 4793 printlevel = printlevel-1; 4703 4794 } 4704 4795 … … 4904 4995 /////////////////////////////////////////////////////////////////////////////// 4905 4996 4906 static proc changeDenominator(ideal U1, poly c1, poly c2, ideal I) 4997 proc changeDenominator(ideal U1, poly c1, poly c2, ideal I) 4998 "USAGE: changeDenominator(U1, c1, c2, I); U1 and I ideals, c1 and c2 4999 polynomials.@* 5000 RETURN: an ideal U2 such that the A-modules 1/c1 * U1 and 1/c2 * U2 are equal, 5001 where A = R/I and R is the basering.@* 5002 NOTE: It assumes that such U2 exists. It is intended maninly as an auxiliary 5003 procedure in the normalization algorithms.@* 5004 EXAMPLE: example changeDenominator; shows an example 5005 " 4907 5006 { 4908 // Given a ring in the form 1/c1 * U, it computes a new ideal U2 such that the4909 // ringis 1/c2 * U2.5007 // Let A = R / I. Given an A-module in the form 1/c1 * U1 (U1 ideal of A), it 5008 // computes a new ideal U2 such that the the A-module is 1/c2 * U2. 4910 5009 // The base ring is R, but the computations are to be done in R / I. 4911 5010 int a; // counter … … 4919 5018 ideal U2 = fetch(Q, U2); 4920 5019 return(U2); 5020 } 5021 example 5022 { 5023 "EXAMPLE:"; 5024 echo = 2; 5025 ring s = 0,(x,y),dp; 5026 ideal I = y5-y4x+4y2x2-x4; 5027 ideal U1 = normal(I)[2][1]; 5028 poly c1 = U1[4]; 5029 U1;c1; 5030 // 1/c1 * U1 is the normalization of I. 5031 ideal U2 = changeDenominator(U1, c1, x3, I); 5032 U2; 5033 // 1/x3 * U2 is also the normalization of I, but with a different denominator. 5034 echo = 0; 4921 5035 } 4922 5036
Note: See TracChangeset
for help on using the changeset viewer.