1pub struct Monomial{
6 a: f64,
7 n: u64,
8}
9
10impl Monomial{
11 pub fn new(a: f64, n:u64) -> Monomial{
13 Monomial{
14 a,
15 n
16 }
17 }
18 pub fn coefficient(&self) -> f64{
20 self.a
21 }
22 pub fn degree(&self) -> u64{
24 self.n
25 }
26 pub fn evaluate(&self, arg: f64) -> f64{
28 self.a*arg.powf(self.n as f64)
29 }
30}
31
32impl Monomial{
33 pub fn derivative(&self) -> Monomial {
35 Monomial{
36 a: self.a*(self.n as f64),
37 n: match self.n{
38 0 => 0,
39 _ => self.n-1,
40 },
41 }
42 }
43 pub fn make_derivative(&mut self) {
45 self.a *= self.n as f64;
46 self.n = match self.n {
47 0 => 0,
48 _ => self.n-1,
49 }
50 }
51}
52
53pub struct Polynomial{
54 terms: Vec<Monomial>,
55}
56
57impl Polynomial{
58 pub fn new(terms: Vec<Monomial>) -> Polynomial{
60 Polynomial{
61 terms,
62 }
63 }
64 pub fn from(terms: Vec<(f64, u64)>) -> Polynomial{
66 Polynomial::new(terms.iter().map(|x| Monomial::new(x.0,x.1)).collect())
67 }
68 pub fn evaluate(&self, arg: f64) -> f64{
70 self.terms.iter().map(|x| x.evaluate(arg)).sum()
71 }
72}
73impl Polynomial{
74 pub fn derivative(&self) -> Polynomial{
76 Polynomial::new(self.terms.iter().map(|x| x.derivative()).collect())
77
78 }
79
80 pub fn solve(&self, guess: f64, iterations: u64) -> f64{
83 let mut x = guess;
84 let prime = self.derivative();
85 for _i in 0..iterations{
86 x = x - self.evaluate(x)/prime.evaluate(x);
87 }
88 x
89 }
90
91 pub fn solve_accurately(&self, guess: f64) -> Result<f64, &str> {
95 let mut difference = 1.0;
96 let mut x = guess;
97 let mut count = 0;
98 while difference > 1e-10 {
99 if count > 100 {
100 return Err("Iteration count exceeded limit- perhaps no solution exists among the reals?");
101 }
102 let old_x = x;
103 x = self.solve(x,1);
104 difference = (x - old_x).abs();
105 count += 1;
106 }
107 if x.is_nan(){
108 return Err("Answer is NaN- try with a different guess?");
109 }
110 Ok(x)
111 }
112}
113
114impl Monomial{
115 fn parse_monomial(string: String) -> Result<Monomial, String>{
117 let mut error = false;
118 let parts: Vec<f64> = string.split("x^").map(|x| match x.parse::<f64>(){
119 Ok(t) => t,
120 Err(_) => {
121 error = true;
122 0.0
123 }
124 }
125 ).collect();
126 if error {
127 return Err("Could not parse expression".to_string());
128 }
129 Ok(Monomial::new(parts[0], parts[1] as u64))
130 }
131}
132
133impl Polynomial{
134
135 pub fn from_string(argstring: String) -> Result<Polynomial, String> {
137 let mut terms: Vec<String> = Vec::new();
138 let mut count = -1;
139
140 for i in argstring.chars().enumerate(){
141 if i.1 == '+' || i.1 == '-' || i.0 == 0{
142 terms.push(i.1.to_string());
143 count += 1;
144 }
145 else {
146 terms[count as usize].push(i.1);
147 }
148 }
149
150 if !terms[0].starts_with('-'){
151 terms[0].insert(0, '+');
152 }
153
154 for i in terms.iter_mut(){
155 if i.starts_with("+x") || i.starts_with("-x") {
156 i.insert(1, '1');
157 }
158
159 match i.find("x"){
160 Some(_) => {},
161 None => i.push_str("x^0"),
162 }
163
164 match i.find("^"){
165 Some(_) => {},
166 None => i.push_str("^1"),
167 }
168 }
169
170 let mut monomials = Vec::new();
171 for i in terms{
172 monomials.push(Monomial::parse_monomial(i.to_string())?);
173 }
174 Ok(Polynomial::new(monomials))
175 }
176
177}
178