source: git/Singular/LIB/urrcount.lib @ f5ba45

spielwiese
Last change on this file since f5ba45 was f5ba45, checked in by Hans Schönemann <hannes@…>, 19 years ago
*GMG: new libs git-svn-id: file:///usr/local/Singular/svn/trunk@8115 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 23.7 KB
Line 
1// $Id: urrcount.lib,v 1.6 2005-05-09 15:55:38 Singular Exp $
2// E. Tobis  12.Nov.2004, April 2004
3// last change 5. May 2005 (G.-M. Greuel)
4///////////////////////////////////////////////////////////////////////////////
5category="Symbolic-numerical solving"
6info="
7LIBRARY: urrcount.lib   Counting number of real roots of univariate polynomial
8AUTHOR:                 Enrique A. Tobis, etobis@dc.uba.ar
9
10OVERVIEW:  Routines for bounding and counting the number of real roots of a
11           univariate polynomial, by means of several different methods, namely
12           Descartes' rule of signs, the Budan-Fourier theorem, Sturm sequences
13           and Sturm-Habicht sequences. The first two give bounds on the number
14           of roots. The other two compute the actual number of roots of the
15           polynomial. There are several wrapper functions, to simplify the
16           application of the aforesaid theorems and some functions
17           to determine whether a given polynomial is univariate.
18           References: Basu, Pollack, Roy, \"Algorithms in Real Algebraic
19           Geometry\", Springer, 2003.
20
21
22PROCEDURES:
23  isuni(p)         Checks whether a polynomials is univariate
24  whichvariable(p) The only variable of a univariate monomial (or 0)
25  varsigns(p)      Number of sign changes in a list
26  boundBuFou(p,a,b) Bound for number of real roots of poly p in interval (a,b)
27  boundposDes(p)   Bound for the number of positive real roots of poly p
28  boundDes(p)      Bound for the number of real roots of poly p
29  allrealst(p)     Checks whether all the roots of a poly are real (via Sturm)
30  maxabs(p)        A bound for the maximum absolute value of a root of a poly
31  allreal(p)       Checks whether all the roots of a poly are real (via St-Ha)
32  sturm(p,a,b)     Number of real roots of a poly on an interval (via Sturm)
33  sturmseq(p)      Sturm sequence of a polynomial
34  sturmha(p,a,b)   Number of real roots of a poly in (a,b) (via Sturm-Habicht)
35  sturmhaseq(p)    A Sturm-Habicht Sequence of a polynomial
36  reverse(l)       Reverses a list
37  nrroots(p)       The number of real roots of p
38  isparam(p)       Returns 0 iff the polynomial has non-parametric coefficients
39
40KEYWORDS:         real roots, univariate polynomial
41";
42///////////////////////////////////////////////////////////////////////////////
43
44static proc isparametric(poly p)
45{
46  int ispar;
47  def ba = basering;
48
49  // If the basering has parameters declared
50  if (npars(basering) != 0) {
51    // If we were given just a polynomial
52    list lba = ringlist(ba);
53    lba[1]=0;
54    def rba = ring(lba); setring rba;
55    poly p1 = imap(ba,p);
56    setring ba;
57    poly p1 = imap(rba,p1);
58    ispar = ispar || (size(p-p1)!=0);
59  }
60  return (ispar);
61}
62///////////////////////////////////////////////////////////////////////////////
63proc isparam(list #)
64"USAGE:     isparam(ideal/module/poly/list);
65RETURN:    int: 0 if the argument has non-parametric coefficients
66           and 1 if it has
67EXAMPLE:   example isparam; shows an example"
68{
69  int i;
70  int ispar;
71  def ar = #[1];
72
73  // It we were given only one argument (not a list)
74  if (size(#) == 1) {
75    if (typeof(ar) == "number") {
76      ispar = (pardeg(ar) > 0);
77    } else {
78    if (typeof(ar) == "poly") {
79      ispar = isparametric(ar);
80    } else {
81    if (typeof(ar) == "ideal" || typeof(ar) == "module") {
82      // Ciclo que revisa cada polinomio
83      i = size(ar);
84      while (!ispar && (i >= 1)) {
85        ispar = ispar || (isparametric(ar[i]));
86        i--;
87      }
88    } else {
89    if (typeof(ar) == "matrix" || typeof(ar) == "intmat") {
90      int j;
91      i = nrows(ar);
92      while (!ispar && (i >= 1)) {
93        j = nrows(ar);
94        while (!ispar && (j >= 1)) {
95          ispar = ispar || (isparametric(ar[i,j]));
96          j--;
97        }
98        i--;
99      }
100    }
101  }}}} else {
102  if (size(#) > 1) {
103    i = size(#);
104    while (!ispar && (i >= 1)) {
105      if ((typeof(#[i]) != "poly") && (typeof(#[i]) != "number") &&
106          typeof(#[i]) != "int") {
107              ERROR("This procedure only works with lists of polynomials");
108      }
109      ispar = ispar || (isparametric(#[i]));
110      i--;
111    }
112  }}
113  return (ispar);
114}
115example
116{
117  echo = 2;
118  ring r = 0,x,dp;
119  isparam(2x3-56x+2);
120  ring s = (0,a,b,c),x,dp;
121  isparam(2x3-56x+2);
122  isparam(2x3-56x+abc);
123}
124///////////////////////////////////////////////////////////////////////////////
125proc isuni(poly p)
126"USAGE:     isuni(p); poly p;
127RETURN:    poly: if p is a univariate polynomial, it returns the variable. If
128           not, zero.
129SEE ALSO:  whichvariable
130EXAMPLE:   example isuni; shows an example"
131{
132  poly variable;
133  poly g;
134  int i;
135  int sofarsogood;
136
137  variable = whichvariable(leadmonom(p));
138
139  if (variable != 0) {
140    i = 1;
141    sofarsogood = 1;
142    while (sofarsogood && i <= size(p)) {
143      g = p[i]/(variable^(deg(p[i])));
144      sofarsogood = sofarsogood && deg(g) == 0;
145      i++;
146    }
147  }
148
149  if (sofarsogood) {
150    return (variable);
151  } else {
152    return (0);
153  }
154}
155example
156{
157  echo = 2;
158  ring r = 0,(x,y),dp;
159  poly p = 6x7-3x2+2x-15/7;
160  isuni(p);
161  isuni(p*y);
162}
163///////////////////////////////////////////////////////////////////////////////
164proc whichvariable(poly p)
165"USAGE:     whichvariable(p); poly p
166RETURN:    poly: if p is a univariate monomial, the variable. Otherwise 0.
167ASSUME:    p is a monomial
168SEE ALSO:  isuni
169EXAMPLE:   example whichvariable; shows an example"
170{
171  int i;
172  int found;
173  poly g;
174  poly variable;
175
176  if (size(p) != 1) {
177    ERROR("p must be a monomial");
178  }
179
180  found = 0;
181
182  i = 1;
183  while (!found && i <= nvars(basering)) {
184    g = diff(p,var(i));
185    if (deg(g) == deg(p) - 1) {
186      // We suspect p is a polynomial in var(i)
187      variable = var(i);
188      found = 1;
189    }
190    i++;
191  }
192
193  // We now have to confirm our suspicion
194  if (found) {
195    if (leadmonom(p/(variable^deg(p))) == 1) { //If p is a monomial on variable
196      return (variable);
197    } else { if (deg(p) <= 0) { // If we received a constant polynomial
198      return (var(1));
199    } else {
200      return (0);
201    }}
202  } else { if (deg(p) <= 0) { // If we received a constant polynomial
203    return (var(1));
204  } else {
205    return (0);
206  }}
207}
208example
209{
210  echo = 2;
211  ring r = 0,(x,y),dp;
212  whichvariable(x5);
213  whichvariable(x3y);
214}
215///////////////////////////////////////////////////////////////////////////////
216proc varsigns(list l)
217"USAGE:     varsigns(l); list l.
218RETURN:    int: the number of sign changes in the list l
219SEE ALSO:  boundposDes
220EXAMPLE:   example varsigns; shows an example"
221{
222  int lastsign;
223  int numberofchanges = 0;
224
225  if (isparam(l)) {
226    ERROR("This procedure cannot operate with parametric arguments");
227  }
228
229  lastsign = sign(l[1]);
230
231  for (int i = 1; i <= size(l); i = i + 1) {
232    if (sign(l[i]) != lastsign && sign(l[i]) != 0) {
233      numberofchanges++;
234      lastsign = sign(l[i]);
235    }
236  }
237  return (numberofchanges);
238}
239example
240{
241  echo = 2;
242  ring r = 0,x,dp;
243  list l = 1,2,3;
244  varsigns(l);
245  l = 1,-1,2,-2,3,-3;
246  varsigns(l);
247}
248///////////////////////////////////////////////////////////////////////////////
249proc boundBuFou(poly p,number a,number b)
250"USAGE:     boundBuFou(p,a,b); p poly, a,b number
251RETURN:    int: an upper bound for the number of real roots of p in (a,b],
252           with the same parity as the actual number of roots (using the
253           Budan-Fourier Theorem)
254ASSUME:    p is a univarite polynomials with rational coefficients
255           a, b are rational numbers with a < b
256SEE ALSO:  boundposDes,varsigns
257EXAMPLE:   example boundBuFou; shows an example"
258{
259  int i;
260  poly variable;
261  list Der;
262  list Dera,Derb;
263  int d;
264  number bound;
265
266  variable = isuni(p);
267
268  if (isparam(p) || isparam(a) || isparam(b)) {
269    ERROR("This procedure cannot operate with parametric arguments");
270  }
271
272  // p must be a univariate polynomial
273  if (variable == 0) {
274    ERROR("p must be a univariate polynomial");
275  }
276
277  if (a >= b) {
278    ERROR("a must be smaller than b");
279  }
280
281  d = deg(p);
282
283  // We calculate the list of derivatives
284
285  Der[d+1] = p;
286
287  for (i = 0;i < d;i++) {
288    Der[d-i] = diff(Der[d-i+1],variable);
289  }
290
291  // Then evaluate that list
292
293  for (i = d+1;i >= 1;i--) {
294    Dera [i] = leadcoef(subst(Der[i],variable,a));
295    Derb [i] = leadcoef(subst(Der[i],variable,b));
296  }
297
298  // Finally we calculate the sign variations
299
300  bound = varsigns(Dera) - varsigns(Derb);
301
302  return(bound);
303}
304example
305{
306  echo = 2;
307  ring r = 0,x,dp;
308  poly p = (x+2)*(x-1)*(x-5);
309  boundBuFou(p,-3,5);
310  boundBuFou(p,-2,5);
311}
312///////////////////////////////////////////////////////////////////////////////
313proc boundposDes(poly p)
314"USAGE:     boundposDes(p); poly p
315RETURN:    int: an upper bound for the number of positive roots of p, with
316           the same parity as the actual number of positive roots of p.
317ASSUME:    p is a univarite polynomials with rational coefficients
318SEE ALSO:  boundBuFou
319EXAMPLE:   example boundposDes; shows an example"
320{
321  poly g;
322  number nroots;
323  poly variable;
324  list coefficients;
325  int i;
326
327  variable = isuni(p);
328
329  if (isparam(p)) {
330    ERROR("This procedure cannot operate with parametric arguments");
331  }
332
333  // p must be a univariate polynomial
334  if (variable == 0) {
335    ERROR("p must be a univariate polynomial");
336  }
337
338  g = p; // We will work with g
339
340  // We check whether 0 is a root of g, and if so, remove it
341  if (subst(g,variable,0) == 0) {
342    g = g/variable^(deg(g[size[g]]));
343  }
344
345  // We count the number of positive roots
346  i = size(g);
347  while (i >= 1) {
348    coefficients[i] = leadcoef(g[i]);
349    i--;
350  }
351  nroots = varsigns(coefficients);
352
353  return(nroots);
354}
355example
356{
357  echo = 2;
358  ring r = 0,x,dp;
359  poly p = (x+2)*(x-1)*(x-5);
360  boundposDes(p);
361
362  p = p*(x2+1);
363
364  boundposDes(p);
365}
366///////////////////////////////////////////////////////////////////////////////
367proc boundDes(poly p)
368"USAGE:     boundDes(p); poly p
369RETURN:    int: an upper bound for the number of real roots of p, with
370           the same parity as the actual number of real roots of p.
371ASSUME:    p is a univarite polynomials with rational coefficients
372SEE ALSO:  boundBuFou
373EXAMPLE:   example boundDes; shows an example"
374{
375  poly g;
376  number nroots;
377  poly variable;
378  list coefficients;
379  int i;
380
381  variable = isuni(p);
382
383  if (isparam(p)) {
384    ERROR("This procedure cannot operate with parametric arguments");
385  }
386
387  // p must be a univariate polynomial
388  if (variable == 0) {
389    ERROR("p must be a univariate polynomial");
390  }
391
392  g = p; // We will work with g
393
394  nroots = 0;
395  // We check whether 0 is a root of g, and if so, remove it
396  if (subst(g,variable,0) == 0) {
397    g = g/variable^(deg(g[size[g]]));
398    nroots++;
399  }
400
401  // We count the number of positive roots
402  i = size(g);
403  while (i >= 1) {
404    coefficients[i] = leadcoef(g[i]);
405    i--;
406  }
407  nroots = nroots + varsigns(coefficients);
408
409  // We count the number of negative roots
410  g = subst(g,variable,-variable);
411  i = size(g);
412  while (i >= 1) {
413    coefficients[i] = leadcoef(g[i]);
414    i--;
415  }
416  nroots = nroots + varsigns(coefficients);
417
418  return(nroots);
419}
420example
421{
422  echo = 2;
423  ring r = 0,x,dp;
424  poly p = (x+2)*(x-1)*(x-5);
425  boundDes(p);
426
427  p = p*(x2+1);
428
429  boundDes(p);
430}
431///////////////////////////////////////////////////////////////////////////////
432proc allrealst(poly p)
433"USAGE:     allrealst(p); poly p
434RETURN:    int: 1 iff all the roots of p are real, 0 otherwise.
435           Checks whether all the roots of p are real by using Sturm's Theorem
436ASSUME:    p is a univarite polynomials with rational coefficients
437SEE ALSO:  allreal,sturm,sturmha
438EXAMPLE:   example allrealst; shows an example"
439{
440  number upper,lower;
441  poly sqfp; // The square-free part of p
442  poly variable;
443
444  variable = isuni(p);
445
446  if (isparam(p)) {
447    ERROR("This procedure cannot operate with parametric arguments");
448  }
449  if (variable == 0) {
450    ERROR ("p must be a univariate polynomial");
451  }
452
453  sqfp = p/gcd(p,diff(p,variable));
454
455  upper = maxabs(sqfp); // By adding one we ensure that sqfp(upper) != 0
456  lower = -upper;
457
458  return (sturm(sqfp,lower,upper) == deg(sqfp));
459}
460example
461{
462  echo = 2;
463  ring r = 0,x,dp;
464  poly p = (x+2)*(x-1)*(x-5);
465  allrealst(p);
466  p = p*(x2+1);
467  allrealst(p);
468}
469///////////////////////////////////////////////////////////////////////////////
470proc maxabs(poly p)
471"USAGE:     maxabs(p); poly p
472RETURN:    number: an upper bound for the largest absolute value of a root of p
473ASSUME:    p is a univarite polynomials with rational coefficients
474SEE ALSO:  sturm
475EXAMPLE:   example maxabs; shows an example"
476{
477  number maximum;
478  poly monic;
479  int i;
480
481  if (isparam(p)) {
482    ERROR("This procedure cannot operate with parametric arguments");
483  }
484
485  monic =  simplify(p,1);
486
487  maximum = 0;
488
489  for (i = 1; i <= size(monic); i = i + 1) {
490    maximum = max(abs(leadcoef(p[i])),maximum);
491  }
492
493  return (maximum + 1);
494}
495example
496{
497  echo = 2;
498  echo = 2;
499  ring r = 0,x,dp;
500  poly p = (x+2)*(x-1)*(x-5);
501  maxabs(p);
502}
503///////////////////////////////////////////////////////////////////////////////
504proc sturm(poly p,number a,number b)
505"USAGE:     sturm(p,a,b); poly p, number a,b
506RETURN:    int: the number of real roots of p in (a,b]
507ASSUME:    p is a univarite polynomials with rational coefficients,
508           a, b are rational numbers with a < b
509SEE ALSO:  sturmha,allrealst,allreal
510EXAMPLE:   example sturm; shows an example"
511{
512  list l;
513  list pa;
514  list pb;
515  int signsA,signsB;
516  int i;
517  int nroots;
518  poly variable;
519
520  if (isparam(p)) {
521    ERROR("This procedure cannot operate with parametric arguments");
522  }
523
524  variable = isuni(p);
525
526  if (variable == 0) {
527    ERROR ("p must be a univariate polynomial");
528  }
529
530  if (a >= b) {
531    ERROR("a must be lower than b");
532  }
533
534  if (subst(p,variable,a) == 0 || subst(p,variable,b) == 0) {
535    ERROR ("Neither a nor b can be roots of P");
536  }
537
538  l = sturmseq(p);
539
540  i = size(l);
541
542  while (i >= 1) { // We build the sequences
543    pa[i] = leadcoef(subst(l[i],variable,a));
544    pb[i] = leadcoef(subst(l[i],variable,b));
545    i--;
546  }
547
548  signsA = varsigns(pa);
549  signsB = varsigns(pb);
550
551  nroots = signsA - signsB + nroots;
552
553  return (nroots);
554}
555example
556{
557  echo = 2;
558  ring r = 0,x,dp;
559  poly p = (x+2)*(x-1)*(x-5);
560  sturm(p,-3,6);
561  p = p*(x2+1);
562  sturm(p,-3,6);
563  p = p*(x+2);
564  sturm(p,-3,6);
565}
566///////////////////////////////////////////////////////////////////////////////
567proc sturmseq(poly p)
568"USAGE:     sturmseq(p); p poly
569RETURN:    list: a Sturm sequence of p
570ASSUME:    p is a univarite polynomials with rational coefficients
571THEORY:    The Sturm sequence of p (also called remainder sequence) is the
572           sequence begininng with p, p' and goes on with minus the remainder
573           of the two previous polynomials, until the remainder is zero.
574           See: Basu, Pollack, Roy, Algorithms in Real Algebraic Geometry,
575           Springer, 2003.
576SEE ALSO:  sturm,sturmhaseq
577EXAMPLE:   example sturmseq; shows an example"
578{
579  list stseq;
580  poly variable;
581  int i;
582
583  variable = isuni(p);
584
585  if (isparam(p)) {
586    ERROR("This procedure cannot operate with parametric arguments");
587  }
588
589  if (variable == 0) {
590    ERROR ("p must be a univariate polynomial");
591  }
592
593  // The two first polynomials in Sturm's sequence
594  stseq = list();
595  stseq[1] = p;
596  stseq[2] = diff(p,variable);
597  poly q = stseq[2];
598  i = 3;
599
600  while (q <>0) {
601    q=reduce(stseq[i-2],std(stseq[i-1]));
602    if (q<>0) {
603      stseq[i] = q;
604    }
605    i++;
606  }
607
608  // Right now, we have gcd(P,P') in stseq[size(stseq)];
609
610  for (i = size(stseq)-1;i >= 1;i--) {
611    stseq[i] = stseq[i]/(sign(leadcoef(stseq[size(stseq)]))*stseq[size(stseq)]);
612    stseq[i] = stseq[i]/abs(leadcoef(stseq[i]));
613  }
614
615  // We divide the gcd by itself
616  stseq[size(stseq)] = sign(leadcoef(stseq[size(stseq)]));
617
618  return (stseq);
619}
620example
621{
622  echo = 2;
623  ring r = 0,(z,x),dp;
624  poly p = x5-3x4+12x3+7x-153;
625  sturmseq(p);
626}
627///////////////////////////////////////////////////////////////////////////////
628proc allreal(poly p)
629"USAGE:     allreal(p);
630RETURN:    int: 1 iff all the roots of p are real, 0 otherwise
631SEE ALSO:  allrealst
632EXAMPLE:   example allreal; shows an example"
633{
634  number upper,lower;
635  poly sqfp; // The square-free part of p
636  poly variable;
637
638  if (isparam(p)) {
639    ERROR("This procedure cannot operate with parametric arguments");
640  }
641
642  variable = isuni(p);
643
644  if (variable == 0) {
645    ERROR ("p must be a univariate polynomial");
646  }
647
648  sqfp = p/gcd(p,diff(p,variable));
649
650  return (sturmha(sqfp,-maxabs(p),maxabs(p)) == deg(sqfp));
651}
652example
653{
654  echo = 2;
655  ring r = 0,x,dp;
656  poly p = (x+2)*(x-1)*(x-5);
657  allreal(p);
658  p = p*(x2+1);
659  allreal(p);
660}
661///////////////////////////////////////////////////////////////////////////////
662proc sturmha(poly P,number a,number b)
663"USAGE:     sturmha(p,a,b); poly p, number a,b
664RETURN:    int: the number of real roots of p in (a,b) (using a
665           Sturm-Habicht sequence)
666SEE ALSO:  sturm,allreal
667EXAMPLE:   example sturmha; shows an example"
668{
669  list seq;
670  int i;
671  list seqa,seqb;
672  poly variable;
673  number bound;
674  //number result;
675  int result;
676
677  if (isparam(P) || isparam(a) || isparam(b)) {
678    ERROR("This procedure cannot operate with parametric arguments");
679  }
680
681  variable = isuni(P);
682
683  if (variable == 0) {
684    ERROR ("P must be a univariate polynomial");
685  }
686
687  if (a >= b) {
688    ERROR("a must be lower than b");
689  }
690
691  if (subst(P,variable,a) == 0 || subst(P,variable,b) == 0) {
692    ERROR ("Neither a nor b can be roots of P");
693  }
694
695  seq = sturmhaseq(P);
696
697  bound = maxabs(P);
698
699  if (a < -bound) {
700    a = -bound;
701  }
702
703  if (b > bound) {
704    b = bound;
705  }
706
707//  if (a == -bound && b == bound) {
708//    for (i = size(seq);i >= 1;i--) {
709//      seq[i] = leadcoef(seq[i]);
710//    }
711//    result = D(seq);
712//  } else {
713    for (i = size(seq);i >= 1;i--) {
714      seqa[i] = leadcoef(subst(seq[i],variable,a));
715      seqb[i] = leadcoef(subst(seq[i],variable,b));
716    }
717    result = (W(seqa) - W(seqb));
718//  }
719  return (result);
720}
721example
722{
723  echo = 2;
724  ring r = 0,x,dp;
725  poly p = (x+2)*(x-1)*(x-5);
726  sturmha(p,-3,6);
727  p = p*(x2+1);
728  sturmha(p,-3,6);
729}
730///////////////////////////////////////////////////////////////////////////////
731proc sturmhaseq(poly P)
732"USAGE:     sturmhaseq(P); P poly.
733RETURN:    list: the nonzero polynomials of the Sturm-Habicht sequence of P
734ASSUME:    P is a univariate polynomial.
735THEORY:    The Sturm-Habicht sequence (also subresultant sequence) is closely
736           related to the Sturm sequence, but behaves better with respect to
737           the size of the coefficients. It is defined via subresultants.
738           See: Basu, Pollack, Roy, Algorithms in Real Algebraic Geometry,
739           Springer, 2003.
740SEE ALSO:  sturm,sturmseq,sturmha
741EXAMPLE:   example sturmhaseq; shows an example"
742{
743  poly Q;
744  poly variable;
745  int p,q,i,j,k,l;
746  list SR;
747  list sr;
748  list srbar;
749  list T;
750
751  if (isparam(P)) {
752    ERROR("This procedure cannot operate with parametric arguments");
753  }
754
755  variable = isuni(P);
756
757  if (variable == 0) {
758    ERROR ("P must be a univariate polynomial");
759  }
760
761  p = deg(P);
762  Q = diff(P,variable);
763  q = deg(Q);
764
765  // Initialization
766  SR[p+2] = sign(leadcoef(P)^(p-q-1))*P;
767//  T[p+2] = SR[p+2];
768
769  srbar[p+2] = sign(leadcoef(P)^(p-q));
770  sr[p+2] = srbar[p+2];
771
772  SR[p-1+2] = sign(leadcoef(P)^(p-q+1))*Q;
773//  T[p-1+2] = SR[p-1+2];
774  srbar[p-1+2] = sign(leadcoef(P)^(p-q+1))*leadcoef(Q);
775
776  i = p+1;
777  j = p;
778
779  while (SR[j-1+2] != 0) {
780    k = deg(SR[j-1+2]);
781    if (k == j-1) {
782      sr[j-1+2] = srbar[j-1+2];
783      SR[k-1+2] = -(reduce(sr[j-1+2]^2*SR[i-1+2],
784                    std(SR[j-1+2])))/(sr[j+2]*srbar[i-1+2]);
785
786//      T[k-1+2] = SR[k-1+2];
787      srbar[k-1+2] = leadcoef(SR[k-1+2]);
788    }
789    if (k < j-1) {
790      // Computation of sr[k+2]
791      for (l = 1;l <= j-k-1;l++) {
792        srbar[j-l-1+2] = ((-1)^l)*(srbar[j-1+2]*srbar[j-l+2])/sr[j+2];
793    }
794    sr[k+2] = srbar[k+2];
795
796      // Computation of SR[k-1+2]
797      SR[k-1+2] = -reduce(srbar[j-1+2]*sr[k+2]*SR[i-1+2],
798                  std(SR[j-1+2]))/(sr[j+2]*srbar[i-1+2]);
799
800      srbar[k-1+2] = leadcoef(SR[k-1+2]);
801
802      SR[k+2] = SR[j-1+2] * ( sr[k+2] / leadcoef(SR[j-1+2]));
803    }
804    i = j;
805    j = k;
806  }
807
808  // We build a new list, discarding the undefined and zero elements
809  // Plus, we reverse the elements
810
811  list filtered;
812  i = size(SR);
813  while (i >= 1) {
814    if (typeof(SR[i]) != "none") {
815      if (SR[i] != 0) {
816        filtered = insert(filtered,SR[i]);
817      }
818    }
819    i--;
820  }
821
822  return (filtered);
823}
824example
825{
826  echo = 2;
827  ring r = 0,x,dp;
828  poly p = x5-x4+x-3/2;
829  list l = sturmhaseq(p);
830  l;
831}
832///////////////////////////////////////////////////////////////////////////////
833proc nrroots(poly p)
834"USAGE:     nrroots(p); poly p
835RETURN:    int: the number of real roots of p
836SEE ALSO:  boundposDes, sturm, sturmha
837EXAMPLE:   example nrroots; shows an example"
838{
839  if (isparam(p)) {
840    ERROR("This procedure cannot operate with parametric arguments");
841  }
842
843  number a = maxabs(p);
844
845  return (sturmha(p,-a,a));
846
847}
848example
849{
850  echo = 2;
851  ring r = 0,x,dp;
852  poly p = (x+2)*(x-1)*(x-5);
853  nrroots(p);
854  p = p*(x2+1);
855  nrroots(p)
856}
857///////////////////////////////////////////////////////////////////////////////
858static proc abs(number x)
859  // Returns the absolute value of x
860{
861  number av;
862
863  if (x >= 0) {
864    av = x;
865  } else {
866    av = -x;
867  }
868
869  return (av);
870}
871///////////////////////////////////////////////////////////////////////////////
872proc sign(number x)
873{
874  int sgn;
875
876  if (isparam(x)) {
877    print(x);
878    ERROR("This procedure cannot operate with parameters");
879  }
880
881  if (x > 0) {
882    sgn = 1;
883  } else { if (x < 0) {
884    sgn = -1;
885  } else {
886    sgn = 0;
887  }}
888
889  return (sgn);
890}
891///////////////////////////////////////////////////////////////////////////////
892static proc max(number a,number b)
893{
894  number maximum;
895
896  if (isparam(a) || isparam(b)) {
897    ERROR("This procedure cannot operate with parameters");
898  }
899
900  if (a > b) {
901    maximum = a;
902  } else {
903    maximum = b;
904  }
905
906  return (maximum);
907}
908///////////////////////////////////////////////////////////////////////////////
909proc reverse(list l)
910"USAGE:     reverse(l); l list
911RETURN:    list: l reversed.
912EXAMPLE:   example reverse; shows an example"
913{
914  int i;
915  list result;
916
917  for (i = 1;i <= size(l);i++) {
918    result = list(l[i]) + result;
919  }
920  return (result);
921}
922example
923{
924  echo = 2;
925  ring r = 0,x,dp;
926  list l = 1,2,3,4,5;
927  list rev = reverse(l);
928  l;
929  rev;
930}
931///////////////////////////////////////////////////////////////////////////////
932static proc D(list l)
933{
934  int p;
935  int q;
936  int i;
937  int sc; // The modified number of sign changes
938
939  if (l[size(l)] == 0) {
940    ERROR("l[size(l)] cannot be 0");
941  }
942
943  sc = 0;
944
945  // We know that l[size(l)]] != 0
946  p = size(l);
947  q = p - 1;
948
949  while (searchnot(l,q,-1,0)) {
950    q = searchnot(l,q,-1,0);
951    if ((p - q) % 2 == 1) { // if p-q is odd
952      sc = sc + ((-1)^(((p-q)*(p-q-1)) / 2))*sign(l[p]*l[q]);
953    }
954    p = q;
955    q = p - 1;
956  }
957
958  return (sc);
959}
960///////////////////////////////////////////////////////////////////////////////
961static proc search(list l,int from,int dir,number element)
962{
963  int i;
964  int result;
965  i = from;
966
967  result = 0;
968
969  while (i + dir >= 0 && i + dir <= size(l) + 1 && !result) {
970    if (l[i] == element) {
971      result = i;
972    }
973    i = i + dir;
974  }
975
976  return (result);
977}
978///////////////////////////////////////////////////////////////////////////////
979static proc searchnot(list l,int from,int dir,number element)
980{
981  int i;
982  int result;
983  i = from;
984
985  result = 0;
986
987  while (i + dir >= 0 && i + dir <= size(l) + 1 && !result) {
988    if (l[i] != element) {
989      result = i;
990    }
991    i = i + dir;
992  }
993
994  return (result);
995}
996///////////////////////////////////////////////////////////////////////////////
997static proc W(list l)
998{
999  int i,temp,sc,lastsign,nofzeros,n;
1000
1001  n = size(l);
1002  sc = 0;
1003  nofzeros = 0;
1004  i = 1;
1005  lastsign = sign(l[i]);
1006
1007  i++;
1008
1009  while (i <= n) {
1010    if (l[i] == 0) {
1011      nofzeros++;
1012    } else {
1013      temp = lastsign * sign(l[i]);
1014
1015      if (temp < 0) {
1016        sc++;
1017      } else {
1018        if (nofzeros == 2) {
1019          sc = sc + 2;
1020        }
1021      }
1022      nofzeros = 0;
1023      lastsign = temp/lastsign;
1024    }
1025    i++;
1026  }
1027  return (sc);
1028}
1029///////////////////////////////////////////////////////////////////////////////
1030
1031
1032
Note: See TracBrowser for help on using the repository browser.