-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpoly.h
250 lines (233 loc) · 10.2 KB
/
poly.h
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
// FILE: poly2.h
// CLASS PROVIDED:
// class polynomial (in the namespace main_savitch_3)
// A polynomial has one variable x, real number coefficients, and
// non-negative integer exponents. Such a polynomial can be viewed
// as having the form:
// A[n]*x^n + A[n-1]*x^(n-1) + ... A[2]*x^2 + A[1]*x + A[0]
// where the A[n] are the real number coefficients and x^i represents
// the variable x raised to the i power. The coefficient A[0] is
// called the "constant" or "zeroth" term of the polynomial.
//
// NOTES TO STUDENT:
// 1. This version works by storing the coefficients in
// a doubly-linked list with each node holding the coefficient and
// exponent for one term. The terms are kept in order from smallest
// to largest exponent. Each polynomial also maintains a pointer to the
// most recently accessed node.
// 2. Note that two functions have been implemented as inline functions
// in this file (the degree and operator() functions).
// 3. An implementation of the make_gif function is available for
// students to use at www.cs.colorado.edu/~main/projects/polygif.cxx.
//
// CONSTRUCTOR for the polynomial class
// POSTCONDITION: This polynomial has been create with all zero
// coefficients, except for coefficient c for the specified exponent.
// When used as a default constructor (using default values for
// both arguments), the result is a polynomial with all zero
// coefficients.
//
// MODIFICATION MEMBER FUNCTIONS for the polynomial class
// void add_to_coef(double amount, unsigned int exponent)
// POSTCONDITION: Adds the given amount to the coefficient of the
// specified exponent.
//
// void assign_coef(double coefficient, unsigned int exponent)
// POSTCONDITION: Sets the coefficient for the specified exponent.
//
// void clear( )
// POSTCONDITION: All coefficients of this polynomial are set to zero.
//
// CONSTANT MEMBER FUNCTIONS for the polynomial class
// double coefficient(unsigned int exponent) const
// POSTCONDITION: Returns coefficient at specified exponent of this
// polynomial.
//
// unsigned int degree( ) const
// POSTCONDITION: The function returns the value of the largest exponent
// with a non-zero coefficient.
// If all coefficients are zero, then the function returns zero.
//
// polynomial derivative( ) const
// POSTCONDITION: The return value is the first derivative of this
// polynomial.
//
// double eval(double x) const
// POSTCONDITION: The return value is the value of this polynomial with the
// given value for the variable x.
//
// void find_root(
// double& answer,
// bool& success,
// unsigned int& iterations,
// double starting_guess = 0,
// unsigned int maximum_iterations = 100,
// double epsilon = 1e-8
// )
// const
// PRECONDITION: epsilon > 0.
// POSTCONDITION: This function uses Newton's method to search for a root
// of the polynomial (i.e., a value of x for which the polynomial is zero).
// The method requires some starting guess for the value of the root. This
// guess is improved over a series of iterations (with the maximum allowed
// iterations defined by the parameter maximum_iterations). There are three
// possible outcomes:
// 1. SUCCESS:
// The method hits a near-root (a value of x for which the absolute
// value of the polynomial is no more than epsilon). In this case, the
// function sets answer to equal this near-root, success is set to true,
// and iterations is set to the number of iterations required.
// 2. FLAT FAILURE:
// Newton's method fails because the guess hits a very flat area of the
// polynomial (a point where first derivative is no more than epsilon).
// In this case, the function sets answer equal to the guess that caused
// flat failure, success is set to false, and iterations is the number
// of iterations carried out (which will be less than
// maximum_iterations).
// 3. MAXIMUM ITERATIONS REACHED:
// The maximum number of iterations is reached without success or flat
// failure. In this case, the function sets answer to the last guess
// tried, success is set to false, and iterations is set to
// maximum_iterations.
//
// unsigned int next_term(unsigned int e) const
// POSTCONDITION: The return value is the next exponent n which is LARGER
// than e such that coefficient(n) != 0.
// If there is no such term, then the return value is zero.
//
// unsigned int previous_term(unsigned int e) const
// POSTCONDITION: The return value is the next exponent n which is SMALLER
// than e such that coefficient(n) != 0.
// If there is no such term, then the return value is UINT_MAX
// from <climits>.
//
// CONSTANT OPERATORS for the polynomial class
// double operator( ) (double x) const
// Same as the eval member function.
//
// NON-MEMBER BINARY OPERATORS for the polynomial Class
// polynomial operator -(const polynomial& p1, const polynomial& p2)
// POSTCONDITION: return-value is a polynomial with each coefficient
// equal to the difference of the coefficients of p1 & p2 for any given
// exponent.
//
// polynomial operator +(const polynomial& p1, const polynomial& p2)
// POSTCONDITION: return-value is a polynomial with each coefficient
// equal to the sum of the coefficients of p1 & p2 for any given
// exponent.
//
// polynomial operator *(const polynomial& p1, const polynomial& p2)
// POSTCONDITION: Each term of p1 has been multiplied by each term of p2,
// and the answer is the sum of all these term-by-term products.
// For example, if p1 is 2x^2 + 3x + 4 and p2 is 5x^2 - 1x + 7, then the
// return value is 10x^4 + 13x^3 + 31x^2 + 17x + 28.
//
// NON-MEMBER OUTPUT FUNCTIONS for the polynomial Class
// ostream& operator << (ostream& out, const polynomial& p)
// POSTCONDITION: The polynomial has been printed to ostream out, which,
// in turn, has been returned to the calling function.
//
// DYNAMIC MEMORY
// Since this class uses dynamic memory, the copy constructor and assignment
// operator are overridden, and there is a destructor implemented. Also,
// if there is insufficient dynamic memory, the following functions throw
// a bad_alloc exception: the constructors, assignment, reserve, add_to_coef,
// assign_coef, and any function that returns a polynomial.
#ifndef POLY2_H
#define POLY2_H
#include <cstdlib> // Provides nullptr
#include <iostream> // Provides ostream
#include <cmath> // provides pow()
#include <climits> // Provides UINT_MAX
#include <limits> // provides machine epsilon
// If your compiler does not support namespaces, then please delete the
// following line and the set of brackets that follow.
namespace main_savitch_5
{
class polynode
{
public:
// CONSTRUCTOR: Creates a node containing a specified initial
// coefficient (init_coef), initial exponent (init_exponent), and
// initial links forward and backward (init_fore and init_back).
polynode(
double init_coef = 0.0,
unsigned int init_exponent = 0,
polynode* init_fore = nullptr,
polynode* init_back = nullptr
)
{
coef_field = init_coef;
exponent_field = init_exponent;
link_fore = init_fore;
link_back = init_back;
}
// Member functions to set the fields:
void set_coef(double new_coef)
{ coef_field = new_coef; }
void set_exponent(unsigned int new_exponent)
{ exponent_field = new_exponent; }
void set_fore(polynode* new_fore)
{ link_fore = new_fore; }
void set_back(polynode* new_back)
{ link_back = new_back; }
// Const member functions to retrieve current coefficient or exponent:
double coef( ) const { return coef_field; }
unsigned int exponent( ) const { return exponent_field; }
// Two slightly different member functions to retrieve each link:
const polynode* fore( ) const { return link_fore; }
polynode* fore( ) { return link_fore; }
const polynode* back( ) const { return link_back; }
polynode* back( ) { return link_back; }
private:
double coef_field;
unsigned int exponent_field;
polynode *link_fore;
polynode *link_back;
};
class polynomial
{
public:
// CONSTRUCTORS and DESTRUCTOR
polynomial(double c = 0.0, unsigned int exponent = 0);
polynomial(const polynomial& source);
~polynomial( );
// MODIFICATION MEMBER FUNCTIONS
polynomial& operator =(const polynomial& source);
void add_to_coef(double amount, unsigned int exponent);
void assign_coef(double coefficient, unsigned int exponent);
void clear( );
// CONSTANT MEMBER FUNCTIONS
double coefficient(unsigned int exponent) const;
unsigned int degree( ) const { return current_degree; }
polynomial derivative( ) const;
double eval(double x) const;
void find_root(
double& answer,
bool& success,
unsigned int& iterations,
double guess = 0,
unsigned int maximum_iterations = 100,
double epsilon = 1e-8
) const;
unsigned int next_term(unsigned int e) const;
unsigned int previous_term(unsigned int e) const;
// CONSTANT OPERATORS
double operator( ) (double x) const { return eval(x); }
private:
double EPSILON;
polynode *head_ptr; // Head pointer for list of terms
polynode *tail_ptr; // Tail pointer for list of terms
mutable polynode *recent_ptr; // Most recently used term
unsigned int current_degree; // Current degree of the polynomial
// A private member function to aid the other functions:
void set_recent(unsigned int exponent) const;
};
// NON-MEMBER BINARY OPERATORS
polynomial operator +(const polynomial& p1, const polynomial& p2);
polynomial operator -(const polynomial& p1, const polynomial& p2);
polynomial operator *(const polynomial& p1, const polynomial& p2);
// NON-MEMBER OUTPUT FUNCTIONS
std::ostream& operator << (std::ostream& out, const polynomial& p);
}
#endif