-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPolynomial.cpp
226 lines (190 loc) · 6.29 KB
/
Polynomial.cpp
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
#include <iostream>
#include <algorithm> // For std::erase AND std::remove_if
#include <regex>
#include "Polynomial.h"
using namespace std;
//-------------------------------------------------------------------
//operator<<
ostream& operator<<(ostream& output, const Polynomial& rhs) {
for (auto it {rhs.polyTerms.crbegin()}; it != rhs.polyTerms.crend(); ++it) {
int exp_i {it->first};
double coef_i {it->second};
output << ' ';
if (coef_i != 1 && coef_i != -1) {
output << showpos << coef_i;
}
else if (exp_i != 0) {//Terms like +1x or -1x
output << (coef_i > 0 ? '+' : '-');
}
else {
output << showpos << coef_i;
}
if (exp_i != 0) {
output << "X";
if (exp_i != 1) {
output << "^" << noshowpos << exp_i ;
}
}
}
return output;
}//end of operator<<
//-------------------------------------------------------------------
//constructor
Polynomial::Polynomial(string input) {
preprocessing(input);
//tokenize input string
tokenize(input);
}//end of constructor
//-------------------------------------------------------------------
//operator+
Polynomial Polynomial::operator+(const Polynomial& rhs) const {
Polynomial temp {*this};
for (auto const& i : rhs.polyTerms) {
temp.polyTerms[i.first] += i.second;
//check if coefficient is zero and if so, delete from polyTerms
if (temp.polyTerms[i.first] == 0) {
temp.polyTerms.erase(i.first);
}
}
return temp;
}//end of operator+
//-------------------------------------------------------------------
//operator-
Polynomial Polynomial::operator-(const Polynomial& rhs) const {
Polynomial temp {*this};
for (auto const& i : rhs.polyTerms) {
temp.polyTerms[i.first] -= i.second;
//check if coefficient is zero and if so, delete from polyTerms
if (temp.polyTerms[i.first] == 0) {
temp.polyTerms.erase(i.first);
}
}
return temp;
}//end of operator-
//-------------------------------------------------------------------
//operator*
Polynomial Polynomial::operator*(const Polynomial& rhs) const {
Polynomial temp;
for (auto const& term1 : this->polyTerms) {
for (auto const& term2 : rhs.polyTerms) {
int exp {term1.first + term2.first};
double coef {term1.second * term2.second};
//add result to the term with same exponent
temp.polyTerms[exp] += coef;
//check if coefficient is zero and if so, delete from polyTerms
if (temp.polyTerms[exp] == 0) {
temp.polyTerms.erase(exp);
}
}
}
return temp;
}//end of operator*
//-------------------------------------------------------------------
//operator/
//https://en.wikipedia.org/wiki/Polynomial_long_division
pair<Polynomial, Polynomial> Polynomial::operator/(const Polynomial& d) const {
Polynomial q;//quotient
Polynomial r {*this};//remainder
//At each step n = d × q + r
while (!r.isEmpty() && degree(r) >= degree(d)) {
//t ← lead(r)/lead(d) # Divide the leading terms
Polynomial t {divLeads(lead(r), lead(d))};
//q ← q + t
q = q + t;
//r ← r − t * d
r = r - t * d;
}
return make_pair(q, r);
}//end of operator/
//-------------------------------------------------------------------
//integral
Polynomial Polynomial::integral(const Polynomial& p) {
Polynomial temp;
for (auto const& i : p.polyTerms) {
int exp {i.first};
double coef {i.second};
temp.polyTerms[exp + 1] += coef / (exp + 1);
}
return temp;
}//end of integral
//-------------------------------------------------------------------
//derivative
Polynomial Polynomial::derivative(const Polynomial& p) {
Polynomial temp;
for (auto const& i : p.polyTerms) {
int exp {i.first};
double coef {i.second};
if (exp != 0) {
temp.polyTerms[exp - 1] += coef * (exp);
}
}
return temp;
}//end of derivative
//-------------------------------------------------------------------
//pre-processing
void Polynomial::preprocessing(string& str) const {
//append '+' to the beginning of string
if (str[ 0 ] != '+' && str[ 0 ] != '-') {
str = '+' + str;
}
//convert terms like '+x' and '-x^2'
//to '+1 x' and '-1 x^2' respectively
regex e(R"(([+-])\s*([xX]))");
str = regex_replace(str, e, "$1 1$2");
//erase spaces
str.erase(
remove_if(str.begin(), str.end(), ::isspace), str.end());
}//end of pre-processing
//-------------------------------------------------------------------
//tokenize
void Polynomial::tokenize(const string& str) {
//tokenize input string
regex e(R"([-+]?((\d*[xX]\^\d+)|(\d*[xX])|(\d+)))");
sregex_token_iterator first(str.begin(), str.end(), e), last;
//convert tokenized string terms to exponent and coefficient
//and then insert them to map<int, double> polyTerms
while (first != last) {
string token {*first++};
smatch sm;
// Terms like "-5x^2" , "+2x^3" , "x^5"
if (regex_match(token, sm, regex(R"(([-+]?\d+)([xX](\^(\d+))?)?)"))) {
double coef {stod(sm[1])};
int exp {0};
string expToken {sm[4].str()};
if (!sm[2].str().empty()) {
if (!expToken.empty()) {// "3x^2" , "x^5"
exp = stoi(expToken);
}
else {// "4x" , "-2X" , "1x"
exp = 1;
}
}
else {// "9" , "-2"
exp = 0;
}
polyTerms[exp] += coef;
//check if coefficient is zero and if and so, delete from polyTerms
if (polyTerms[exp] == 0) {
polyTerms.erase(exp);
}
}
}
}//end of tokenize
//-------------------------------------------------------------------
//degree
int Polynomial::degree(const Polynomial& p) {
if (p.isEmpty()) {
return 0;
}
else {
return p.maxTerm().first;
}
}//end of degree
//-------------------------------------------------------------------
//divLeads calculate lead(r)/lead(d)
Polynomial Polynomial::divLeads(const Polynomial& op1, const Polynomial& op2) {
int exp_t {op1.maxTerm().first - op2.maxTerm().first};
double coef_t {op1.maxTerm().second / op2.maxTerm().second};
map<int, double> map_t {make_pair(exp_t, coef_t)};
return Polynomial{map_t};
}//end of divLeads