File: roottest.cpp

package info (click to toggle)
pluto-find-orb 0.0~git20180227-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,668 kB
  • sloc: cpp: 30,743; makefile: 263
file content (158 lines) | stat: -rw-r--r-- 4,164 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#define MAX_POLY 10

int find_real_polynomial_roots( const double *poly, int poly_degree,
                                double *real_roots);        /* roots.cpp */

/* Compile with

g++ -Wall -O3 -Wextra -pedantic -o roottest roottest.cpp roots.cpp

This tests the code in 'roots.cpp' for finding all real roots of a
polynomial with all real coefficients.  Run it with without command
line arguments to get a description.   */

static int extract_polynomial( const char *buff, double *poly)
{
   unsigned i;

   for( i = 0; i < MAX_POLY; i++)
      poly[i] = 0.;
   while( *buff)
      {
      double coeff = atof( buff);

      if( coeff == 0.)
         coeff = (*buff == '-' ? -1. : 1.);
      while( *buff && *buff != 'x')
         buff++;
      if( !*buff)    /* constant term */
         i = 0;
      else if( buff[1] == '^')
         {
         buff += 2;
         i = (unsigned)atoi( buff);
         if( i <= 1)
            return( -1);
         while( *buff >= '0' && *buff <= '9')
            buff++;
         }
      else                    /* linear term */
         {
         buff++;
         i = 1;
         }
      poly[i] = coeff;
      }
   return( 0);
}

static int extract_full_polynomial( const char *buff, double *poly)
{
   unsigned i, j;
   bool first_time = true;

   if( *buff != '(')       /* no factors;  plain old polynomial */
      return( extract_polynomial( buff, poly));
   while( *buff)
      {
      char tbuff[100];

      while( *buff && *buff != '(')
         buff++;
      buff++;
      for( i = 0; buff[i] && buff[i] != ')'; i++)
         tbuff[i] = buff[i];
         ;
      if( !buff[i])     /* didn't find closing paren */
         return( -3);
      tbuff[i] = '\0';
      buff += i + 1;
      if( first_time)
         {
         first_time = false;
         extract_polynomial( tbuff, poly);
         }
      else        /* multiplying by a second,  or third,  or... term */
         {
         double tpoly[MAX_POLY], product[MAX_POLY];

         extract_polynomial( tbuff, tpoly);
         for( i = 0; i < MAX_POLY; i++)
            product[i] = 0.;
         for( i = 0; i < MAX_POLY; i++)
            for( j = 0; j + i < MAX_POLY; j++)
               product[i + j] += poly[i] * tpoly[j];
         for( i = 0; i < MAX_POLY; i++)
            poly[i] = product[i];
         }
      }
   return( 0);
}

static void remove_spaces( char *buff)
{
   char *optr = buff;

   while( *buff)
      {
      if( *buff != ' ')
         *optr++ = *buff;
      buff++;
      }
   *optr = '\0';
}

int main( const int argc, const char **argv)
{
   char poly_text[1000];
   double poly[MAX_POLY], roots[MAX_POLY];
   int err_code = -99, i, order = 0, n_roots;

   *poly_text = '\0';
   for( i = 1; i < argc; i++)
      strcat( poly_text, argv[i]);
   remove_spaces( poly_text);
   if( *poly_text)
      err_code = extract_full_polynomial( poly_text, poly);
   if( err_code)
      {
      printf( "Error in parsing polynomial: %d\n", err_code);
      printf( "'roottest' will find all _real_ roots of a given polynomial with\n");
      printf( "real coefficients,  guaranteed,  but no complex ones. For example :\n\n");
      printf( "./roottest \"(12 x^2 + x - 1)*(x-2)\"\n");
      printf( "./roottest +12 * x ^ 3 -23 * x ^ 2 -3 * x+2\n\n");
      printf( "would both result in finding roots at x=-1/3, x=1/4,  and x=2.\n");
      printf( "Method is described in 'roots.cpp'.\n");
      return( -1);
      }
   for( i = MAX_POLY - 1; i >= 1; i--)
      if( poly[i] != 0.)
         {
         if( poly[i] == 1.)
            printf( " + x");
         else if( poly[i] == -1.)
            printf( " - x");
         else
            printf( " %+g * x", poly[i]);
         if( i > 1)
            printf( " ^ %d", i);
         }
   if( poly[0] != 0.)
      printf( "%+g", poly[0]);
   printf( "\n");

   for( i = 0; i < MAX_POLY; i++)
      if( poly[i] != 0.)
         order = i;
   n_roots = find_real_polynomial_roots( poly, order, roots);
   for( i = 0; i < n_roots; i++)
      printf( "%f is a root\n", roots[i]);
   return( 0);
}