1#[allow(unused_imports)]
2use crate::structure::matrix::*;
3#[allow(unused_imports)]
4use crate::structure::vector::*;
5use crate::util::useful::*;
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::traits::fp::FPVector;
10use peroxide_num::PowOps;
11use std::cmp::{max, min};
12use std::fmt;
13use std::ops::{Add, Div, Mul, Neg, Sub};
14
15#[derive(Debug, Clone, Default)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[cfg_attr(
22 feature = "rkyv",
23 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
24)]
25pub struct Polynomial {
26 pub coef: Vec<f64>,
27}
28
29impl fmt::Display for Polynomial {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 let mut result = String::new();
45 let l = self.coef.len() - 1;
46
47 if l == 0 {
48 let value = self.coef[0];
49 let temp = choose_shorter_string(format!("{}", value), format!("{:.4}", value));
50 return write!(f, "{}", temp);
51 }
52
53 if l == 1 {
54 let coef_1 = self.coef[0];
55 let coef_0 = self.coef[1];
56
57 if coef_1 == 1. {
58 result.push('x');
59 } else if coef_1 == -1. {
60 result.push_str("-x");
61 } else {
62 let temp = choose_shorter_string(format!("{}x", coef_1), format!("{:.4}x", coef_1));
63 result.push_str(&temp);
64 }
65
66 if coef_0 > 0. {
67 let temp =
68 choose_shorter_string(format!(" + {}", coef_0), format!(" + {:.4}", coef_0));
69 result.push_str(&temp);
70 } else if coef_0 < 0. {
71 let temp = choose_shorter_string(
72 format!(" - {}", coef_0.abs()),
73 format!(" - {:.4}", coef_0.abs()),
74 );
75 result.push_str(&temp);
76 }
77 return write!(f, "{}", result);
78 }
79
80 for i in 0..l + 1 {
81 match i {
82 0 => {
83 let value = self.coef[i];
84 if value == 1. {
85 result.push_str(&format!("x^{}", l));
86 } else if value == -1. {
87 result.push_str(&format!("-x^{}", l));
88 } else {
89 let temp = choose_shorter_string(
90 format!("{}x^{}", value, l),
91 format!("{:.4}x^{}", value, l),
92 );
93 result.push_str(&temp);
94 }
95 }
96 i if i == l => {
97 let value = self.coef[i];
98 if value > 0. {
99 let temp = choose_shorter_string(
100 format!(" + {}", value),
101 format!(" + {:.4}", value),
102 );
103 result.push_str(&temp);
104 } else if value < 0. {
105 let temp = choose_shorter_string(
106 format!(" - {}", value.abs()),
107 format!(" - {:.4}", value.abs()),
108 );
109 result.push_str(&temp);
110 }
111 }
112 i if i == l - 1 => {
113 let value = self.coef[i];
114 if value == 1. {
115 result.push_str(" + x");
116 } else if value > 0. {
117 let temp = choose_shorter_string(
118 format!(" + {}x", value),
119 format!(" + {:.4}x", value),
120 );
121 result.push_str(&temp);
122 } else if value == -1. {
123 result.push_str(" - x");
124 } else if value < 0. {
125 let temp = choose_shorter_string(
126 format!(" - {}x", value.abs()),
127 format!(" - {:.4}x", value.abs()),
128 );
129 result.push_str(&temp);
130 }
131 }
132 _ => {
133 let value = self.coef[i];
134 if value == 1. {
135 result.push_str(&format!(" + x^{}", l - i));
136 } else if value > 0. {
137 let temp = choose_shorter_string(
138 format!(" + {}x^{}", value, l - i),
139 format!(" + {:.4}x^{}", value, l - i),
140 );
141 result.push_str(&temp);
142 } else if value == -1. {
143 result.push_str(&format!(" - x^{}", l - i));
144 } else if value < 0. {
145 let temp = choose_shorter_string(
146 format!(" - {}x^{}", value.abs(), l - i),
147 format!(" - {:.4}x^{}", value.abs(), l - i),
148 );
149 result.push_str(&temp);
150 }
151 }
152 }
153 }
154 write!(f, "{}", result)
155 }
156}
157
158impl Polynomial {
159 pub fn new(coef: Vec<f64>) -> Self {
161 Self { coef }
162 }
163
164 pub fn eval<T>(&self, x: T) -> f64
185 where
186 T: Into<f64> + Copy,
187 {
188 let x = x.into();
189 let l = self.coef.len() - 1;
190 let mut s = self.coef[0];
191 for i in 0..l {
192 s = self.coef[i + 1] + x * s;
193 }
194 s
195 }
196
197 pub fn eval_vec(&self, v: Vec<f64>) -> Vec<f64> {
198 v.fmap(|t| self.eval(t))
199 }
200
201 pub fn translate_x<X>(&self, x: X) -> Self
217 where
218 X: Into<f64> + Copy,
219 {
220 let d = Self::new(vec![1f64, x.into()]);
221
222 let mut coef = vec![0f64; self.coef.len()];
223
224 let (mut p, ri) = self.horner_division(&d);
225 coef[self.coef.len() - 1] = ri;
226
227 for i in (0..(self.coef.len() - 1)).rev() {
228 if p.coef.len() == 1 {
229 coef[i] = p.coef[0];
230 break;
231 }
232
233 let t = p.horner_division(&d);
234 coef[i] = t.1;
235 p = t.0;
236 }
237
238 Self::new(coef)
239 }
240
241 pub fn horner_division(&self, other: &Self) -> (Self, f64) {
242 assert_eq!(other.coef.len(), 2usize);
243 assert_eq!(other.coef[0], 1.0f64);
244
245 let mut coef = vec![0f64; self.coef.len() - 1];
246 coef[0] = self.coef[0];
247
248 let d = other.coef[1];
249 for i in 1..coef.len() {
250 coef[i] = self.coef[i] - d * coef[i - 1];
251 }
252
253 let remainder = self.coef[self.coef.len() - 1] - d * coef[coef.len() - 1];
254 (Self::new(coef), remainder)
255 }
256}
257
258pub fn poly(coef: Vec<f64>) -> Polynomial {
260 Polynomial::new(coef)
261}
262
263impl Neg for Polynomial {
268 type Output = Self;
269
270 fn neg(self) -> Self::Output {
271 Self::new(
272 self.coef
273 .clone()
274 .into_iter()
275 .map(|x| -x)
276 .collect::<Vec<f64>>(),
277 )
278 }
279}
280
281impl Add<Polynomial> for Polynomial {
282 type Output = Self;
283 fn add(self, other: Self) -> Self {
284 let (l1, l2) = (self.coef.len(), other.coef.len());
285 let l_max = max(l1, l2);
286 let l_min = min(l1, l2);
287 let v_max = choose_longer_vec(&self.coef, &other.coef);
288 let v_min = choose_shorter_vec(&self.coef, &other.coef);
289 let mut coef = vec![0f64; l_max];
290
291 for i in 0..l_max {
292 if i < l_max - l_min {
293 coef[i] = v_max[i];
294 } else {
295 let j = i - (l_max - l_min);
296 coef[i] = v_max[i] + v_min[j];
297 }
298 }
299 Self::new(coef)
300 }
301}
302
303impl<T> Add<T> for Polynomial
304where
305 T: Into<f64> + Copy,
306{
307 type Output = Self;
308 fn add(self, other: T) -> Self {
309 let mut new_coef = self.coef.clone();
310 new_coef[self.coef.len() - 1] += other.into();
311 Self::new(new_coef)
312 }
313}
314
315impl Sub<Polynomial> for Polynomial {
316 type Output = Self;
317 fn sub(self, other: Self) -> Self {
318 self.add(other.neg())
319 }
320}
321
322impl<T> Sub<T> for Polynomial
323where
324 T: Into<f64> + Copy,
325{
326 type Output = Self;
327 fn sub(self, other: T) -> Self {
328 let mut new_coef = self.coef.clone();
329 new_coef[self.coef.len() - 1] -= other.into();
330 Self::new(new_coef)
331 }
332}
333
334impl<T> Mul<T> for Polynomial
335where
336 T: Into<f64> + Copy,
337{
338 type Output = Self;
339 fn mul(self, other: T) -> Self {
340 Self::new(
341 self.coef
342 .into_iter()
343 .map(|x| x * other.into())
344 .collect::<Vec<f64>>(),
345 )
346 }
347}
348
349impl Mul<Polynomial> for Polynomial {
350 type Output = Self;
351 fn mul(self, other: Self) -> Self {
352 let (l1, l2) = (self.coef.len(), other.coef.len());
353 let (n1, n2) = (l1 - 1, l2 - 1);
354 let n = n1 + n2;
355 let mut result = vec![0f64; n + 1];
356
357 for i in 0..l1 {
358 let fixed_val = self.coef[i];
359 let fixed_exp = n1 - i;
360
361 for j in 0..l2 {
362 let target_val = other.coef[j];
363 let target_exp = n2 - j;
364
365 let result_val = fixed_val * target_val;
366 let result_exp = fixed_exp + target_exp;
367
368 result[n - result_exp] += result_val;
369 }
370 }
371
372 Self::new(result)
373 }
374}
375
376impl<T> Div<T> for Polynomial
377where
378 T: Into<f64> + Copy,
379{
380 type Output = Self;
381 fn div(self, other: T) -> Self {
382 let val = other.into();
383 assert_ne!(val, 0f64);
384
385 Self::new(self.coef.fmap(|x| x / val))
386 }
387}
388
389impl Div<Polynomial> for Polynomial {
390 type Output = (Self, Self);
391 fn div(self, other: Self) -> Self::Output {
392 let l1 = self.coef.len();
393 let l2 = other.coef.len();
394 assert!(l1 >= l2);
395
396 let mut temp = self.clone();
397 let mut quot_vec: Vec<f64> = Vec::new();
398 let denom = other.coef[0];
399
400 while temp.coef.len() >= l2 {
401 let l = temp.coef.len();
402 let target = temp.coef[0];
403 let nom = target / denom;
404 quot_vec.push(nom);
405 let mut temp_vec = vec![0f64; l - 1];
406
407 for i in 1..l {
408 if i < l2 {
409 temp_vec[i - 1] = temp.coef[i] - nom * other.coef[i];
410 } else {
411 temp_vec[i - 1] = temp.coef[i];
412 }
413 }
414
415 temp = poly(temp_vec);
416 }
417
418 let rem = temp;
419
420 (poly(quot_vec), rem)
421 }
422}
423
424impl Mul<Polynomial> for usize {
425 type Output = Polynomial;
426
427 fn mul(self, rhs: Polynomial) -> Self::Output {
428 rhs.mul(self as f64)
429 }
430}
431
432impl Mul<Polynomial> for i32 {
433 type Output = Polynomial;
434
435 fn mul(self, rhs: Polynomial) -> Self::Output {
436 rhs.mul(self as f64)
437 }
438}
439
440impl Mul<Polynomial> for i64 {
441 type Output = Polynomial;
442
443 fn mul(self, rhs: Polynomial) -> Self::Output {
444 rhs.mul(self as f64)
445 }
446}
447
448impl Mul<Polynomial> for f32 {
449 type Output = Polynomial;
450
451 fn mul(self, rhs: Polynomial) -> Self::Output {
452 rhs.mul(self as f64)
453 }
454}
455
456impl Mul<Polynomial> for f64 {
457 type Output = Polynomial;
458
459 fn mul(self, rhs: Polynomial) -> Self::Output {
460 rhs.mul(self)
461 }
462}
463
464impl PowOps for Polynomial {
468 type Float = f64;
469 fn powi(&self, n: i32) -> Self {
470 let mut result = self.clone();
471 for _i in 0..n - 1 {
472 result = result * self.clone();
473 }
474 result
475 }
476
477 fn powf(&self, _f: f64) -> Self {
478 unimplemented!()
479 }
480
481 fn pow(&self, _f: Self) -> Self {
482 unimplemented!()
483 }
484
485 fn sqrt(&self) -> Self {
486 unimplemented!()
487 }
488}
489
490pub trait Calculus {
494 fn derivative(&self) -> Self;
495 fn integral(&self) -> Self;
496 fn integrate<T: Into<f64> + Copy>(&self, interval: (T, T)) -> f64;
497}
498
499impl Calculus for Polynomial {
500 fn derivative(&self) -> Self {
501 let l = self.coef.len() - 1;
502 let mut result = vec![0f64; l];
503
504 for i in 0..l {
505 result[i] = self.coef[i] * (l - i) as f64;
506 }
507 Self::new(result)
508 }
509
510 fn integral(&self) -> Self {
511 let l = self.coef.len();
512 let mut result = vec![0f64; l + 1];
513
514 for i in 0..l {
515 result[i] = self.coef[i] / (l - i) as f64;
516 }
517 Self::new(result)
518 }
519
520 fn integrate<T: Into<f64> + Copy>(&self, interval: (T, T)) -> f64 {
521 let (a, b) = (interval.0.into(), interval.1.into());
522 let integral = self.integral();
523 integral.eval(b) - integral.eval(a)
524 }
525}
526
527pub fn lagrange_polynomial(node_x: Vec<f64>, node_y: Vec<f64>) -> Polynomial {
532 assert_eq!(node_x.len(), node_y.len());
533 let l = node_x.len();
534
535 if l <= 1 {
536 panic!("Lagrange Polynomial needs at least 2 nodes");
537 } else if l == 2 {
538 let p0 = poly(vec![1f64, -node_x[0]]);
539 let p1 = poly(vec![1f64, -node_x[1]]);
540
541 let a = node_y[1] / (node_x[1] - node_x[0]);
542 let b = -node_y[0] / (node_x[1] - node_x[0]);
543
544 p0 * a + p1 * b
545 } else if l == 3 {
546 let p0 = poly(vec![1f64, -(node_x[0] + node_x[1]), node_x[0] * node_x[1]]);
547 let p1 = poly(vec![1f64, -(node_x[0] + node_x[2]), node_x[0] * node_x[2]]);
548 let p2 = poly(vec![1f64, -(node_x[1] + node_x[2]), node_x[1] * node_x[2]]);
549
550 let a = node_y[2] / ((node_x[2] - node_x[0]) * (node_x[2] - node_x[1]));
551 let b = node_y[1] / ((node_x[1] - node_x[0]) * (node_x[1] - node_x[2]));
552 let c = node_y[0] / ((node_x[0] - node_x[1]) * (node_x[0] - node_x[2]));
553
554 p0 * a + p1 * b + p2 * c
555 } else {
556 let mut result = Polynomial::new(vec![0f64; l]);
557
558 for i in 0..l {
559 let fixed_val = node_x[i];
560 let prod = node_y[i];
561 let mut id = poly(vec![1f64]);
562
563 for j in 0..l {
564 if j == i {
565 continue;
566 } else {
567 let target_val = node_x[j];
568 let denom = fixed_val - target_val;
569 id = id * (poly(vec![1f64, -target_val]) / denom);
570 }
571 }
572 result = result + (id * prod);
573 }
574 result
575 }
576}
577
578pub fn legendre_polynomial(n: usize) -> Polynomial {
583 match n {
584 0 => poly(vec![1f64]), 1 => poly(vec![1f64, 0f64]), 2 => poly(vec![1.5, 0f64, -0.5]),
587 3 => poly(vec![2.5, 0f64, -1.5, 0f64]),
588 _ => {
589 let k = n - 1;
590 let k_f64 = k as f64;
591 ((2f64 * k_f64 + 1f64) * poly(vec![1f64, 0f64]) * legendre_polynomial(k)
592 - k_f64 * legendre_polynomial(k - 1))
593 / (k_f64 + 1f64)
594 }
595 }
596}
597
598#[derive(Debug, Clone, Copy, PartialEq, Eq)]
599pub enum SpecialKind {
600 First,
601 Second,
602}
603
604pub fn chebyshev_polynomial(n: usize, kind: SpecialKind) -> Polynomial {
606 let mut prev = Polynomial::new(vec![1f64]);
607 let mut curr = match kind {
608 SpecialKind::First => Polynomial::new(vec![1f64, 0f64]),
609 SpecialKind::Second => Polynomial::new(vec![2f64, 0f64]),
610 };
611
612 match n {
613 0 => prev,
614 1 => curr,
615 _ => {
616 for _i in 1..n {
617 std::mem::swap(&mut prev, &mut curr);
618 curr = poly(vec![2f64, 0f64]) * prev.clone() - curr;
619 }
620 curr
621 }
622 }
623}
624
625pub fn hermite_polynomial(n: usize) -> Polynomial {
631 let mut prev = Polynomial::new(vec![1f64]); let mut curr = Polynomial::new(vec![2f64, 0f64]); match n {
635 0 => prev,
636 1 => curr,
637 _ => {
638 for idx in 1..n {
639 let k = idx as f64;
640 std::mem::swap(&mut prev, &mut curr);
641 curr = poly(vec![2f64, 0f64]) * prev.clone() - 2.0 * k * curr;
642 }
643 curr
644 }
645 }
646}
647
648pub fn bessel_polynomial(n: usize) -> Polynomial {
654 let mut prev = Polynomial::new(vec![1f64]); let mut curr = Polynomial::new(vec![1f64, 1f64]); match n {
658 0 => prev,
659 1 => curr,
660 _ => {
661 for idx in 1..n {
662 let k = idx as f64;
663 std::mem::swap(&mut prev, &mut curr);
664 curr = (2.0 * k + 1.0) * poly(vec![1f64, 0f64]) * prev.clone() + curr;
665 }
666 curr
667 }
668 }
669}