source: git/Singular/LIB/rootsur.lib @ 341696

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