erosion/
lib.rs

1//! Erosion
2//!  A library to plot Fourier Curves and Non-Continous Functions
3
4pub mod prelude{
5    use std::error::Error;
6    pub trait Plottable{
7        fn plot(self:&Self, output_file:&str, caption:&str, x_bound:(f32,f32), y_bound:(f32,f32), step:f32)->Result<(),Box<dyn Error>>;
8    }
9
10    pub trait Substitute{
11        fn substitute(self:&Self, x:f64)->f64;
12    }
13
14    pub trait Ordinal{
15        fn ord(self:&Self)->f64;
16    }
17    pub trait Bounded{
18        fn in_bounds(self:&Self, x:f64)->bool;
19    }
20
21    pub trait Calculus{
22        fn integrate(self: &Self)-> Self;
23        fn differenciate(self: &Self)->Self;
24    }
25}
26
27
28
29pub mod curves{
30    use plotters::prelude::*;
31    use super::prelude::*;
32    use std::{error::Error, f64::consts::PI, ops::{Add, Mul, Div, Sub, AddAssign, SubAssign, MulAssign, DivAssign}};
33    #[derive(Debug, Clone, Copy, PartialEq)]
34    pub enum Type{
35        Sine,
36        Cosine,
37    }
38    impl Type{
39        pub fn inv(self:&Self)->Type{
40            match self{
41                Type::Sine=>Type::Cosine,
42                Type::Cosine=>Type::Sine,
43            }
44        }
45    }
46    
47    impl Add<f64> for Type{
48        type Output = f64;
49        fn add(self, rhs: f64) -> Self::Output {
50            match self{
51                Type::Sine=>rhs,
52                Type::Cosine=>rhs+PI/2.,
53            }
54        }
55    }
56
57    /// A sine curve in the form 
58    /// mag * sine ( fre * ( x + phase ) )
59    #[derive(Debug, Clone, Copy, PartialEq)]
60    pub struct Curve{
61        pub mag : f64,
62        pub fre : f64,
63        pub phase : Type,
64    }
65
66    impl Curve{
67        pub fn new(mag:f64, fre:f64, phase:Type)->Self{
68            Self{mag, fre, phase}
69        }
70    } // impl Curve
71    /// sub into Curve a value for theta
72    impl Substitute for Curve{
73        fn substitute(self:&Self, x:f64)->f64{
74            self.mag*(self.fre*(self.phase + x)).sin()
75        }
76    }
77    impl Calculus for Curve{
78        fn integrate(self: &Self) -> Self {
79            match self.phase{
80                Type::Sine=>Self{
81                    mag: self.mag/self.fre * -1.,
82                    fre: self.fre,
83                    phase: Type::Cosine,
84                },
85                Type::Cosine=>Self{
86                    mag: self.mag/self.fre,
87                    fre: self.fre,
88                    phase: Type::Sine,
89                }
90            }
91        }
92        fn differenciate(self: &Self) ->Self {
93            match self.phase{
94                Type::Sine=>Self{
95                    mag: self.mag*self.fre,
96                    fre: self.fre,
97                    phase: Type::Cosine,
98                },
99                Type::Cosine=>Self{
100                    mag: self.mag*self.fre * -1.,
101                    fre: self.fre,
102                    phase: Type::Sine,
103                }
104            }
105        }
106    }
107    impl AddAssign for Curve{
108        fn add_assign(&mut self, rhs: Self) {
109            if let Some(c) = *self + rhs{
110                *self = c;
111            }
112        }
113    }
114    impl SubAssign for Curve{
115        fn sub_assign(&mut self, rhs: Self) {
116            if let Some(c) = *self - rhs{
117                *self = c;
118            }
119        }
120    }
121    impl MulAssign<f64> for Curve{
122        fn mul_assign(&mut self, rhs: f64) {
123            *self = *self * rhs;
124        }
125    }
126    impl DivAssign<f64> for Curve{
127        fn div_assign(&mut self, rhs: f64) {
128            *self = *self / rhs;
129        }
130    }
131    impl Add<Curve> for Curve{
132        type Output = Option<Curve>;
133        fn add(self, rhs: Self) -> Self::Output {
134            if self.fre == rhs.fre && self.phase == rhs.phase{
135                return Some(
136                    Curve::new(
137                        self.mag + rhs.mag,
138                        self.fre,
139                        self.phase
140                    )
141                )
142            }
143            None
144        }
145    }
146    impl Sub<Curve> for Curve{
147        type Output = Option<Curve>;
148        fn sub(self, rhs: Self) -> Self::Output {
149            if self.fre == rhs.fre && self.phase == rhs.phase{
150                return Some(
151                    Curve::new(
152                        self.mag - rhs.mag,
153                        self.fre,
154                        self.phase
155                    )
156                )
157            }
158            None
159        }
160    }
161    impl Mul<f64> for Curve{
162        type Output = Curve;
163        fn mul(self, rhs: f64) -> Self::Output {
164            Self::Output{
165                mag: self.mag*rhs,
166                fre:self.fre,
167                phase: self.phase,
168            }
169        }
170    }
171    impl Div<f64> for Curve{
172        type Output = Curve;
173        fn div(self, rhs:f64) -> Self::Output{
174            Self::Output{
175                mag : self.mag/rhs,
176                fre: self.fre,
177                phase : self.phase
178            }
179        }
180    }
181
182    #[derive(Debug, Clone)]
183    pub struct FourierCurve{
184        pub curves: Vec<Curve>,
185    }
186    impl FourierCurve{
187        pub fn new()->Self{
188            FourierCurve{
189                curves:Vec::new(),
190            }
191        }
192        /// push a curve into the Fourier Curve
193        pub fn push(self:& mut Self, curve: Curve){
194            self.curves.push(curve);
195        }
196        /// push components of a Curve into the Fourier Curve
197        pub fn push_curve(self:&mut Self, mag:f64, fre:f64, phase:Type){
198            self.push(Curve::new(mag, fre, phase));
199        }
200        
201    } // impl FourierCourve
202    impl Into<Vec<f64>> for FourierCurve{
203        fn into(self) -> Vec<f64> {
204            let mut result:Vec<f64> = Vec::new();
205            let x_axis = (-3.14..3.14).step(0.01);
206            for val in x_axis.values(){
207                result.push(self.substitute(val));
208            }
209            // read up to 10 bytes
210            result
211        }
212    }
213    impl Calculus for FourierCurve{
214        fn integrate(self: &Self) -> Self {
215            let mut f = FourierCurve::new();
216            for c in &self.curves{
217                f = f + c.integrate();
218            }
219            f
220
221        }
222        fn differenciate(self: &Self) ->Self {
223            let mut f = FourierCurve::new();
224            for c in &self.curves{
225                f = f + c.differenciate();
226            }
227            f
228        }
229    }
230
231    impl Plottable for FourierCurve{
232    
233        fn plot(self:&Self, output_file:&str, caption:&str, x_bound:(f32,f32), y_bound:(f32,f32), step:f32)->Result<(),Box<dyn Error>>{
234            let root = BitMapBackend::new(output_file,(640,480)).into_drawing_area();
235            root.fill(&WHITE)?;
236
237            let mut chart = ChartBuilder::on(&root)
238                .x_label_area_size(35)
239                .y_label_area_size(40)
240                .margin(5)
241                .caption(caption, ("sans-serif", 50.0))
242                .build_cartesian_2d(x_bound.0..x_bound.1, y_bound.0..y_bound.1)?;
243
244            chart.configure_mesh()
245                .x_labels(20)
246                .y_labels(10)
247                .disable_mesh()
248                .x_label_formatter(&|v| format!("{:.1}", v))
249                .y_label_formatter(&|v| format!("{:.1}", v))
250                .draw()?;
251                
252            let x_axis = (x_bound.0..x_bound.1).step(step);
253            chart.draw_series(LineSeries::new(x_axis.values().map(|x| (x, self.substitute(x as f64) as f32)), &RED))?;
254            //.label("Curve")
255            //.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
256            //chart.configure_series_labels().border_style(&BLACK).draw()?;
257
258            root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir");
259            println!("Result has been saved to {}", output_file);
260            Ok(())
261    
262        }
263    }// impl Plotable for FourierCurve
264    impl Substitute for FourierCurve{
265        fn substitute(self:&Self, x:f64)->f64{
266            let mut sum = 0.0;
267            for c in &self.curves{
268                sum= sum + c.substitute(x);
269            }
270            sum
271        }
272    }
273    impl PartialEq for FourierCurve{
274        fn eq(&self, other: &Self) -> bool {
275            for a in &self.curves{
276                if !other.curves.contains(a){
277                    return false
278                }
279            }
280            true
281        }
282    }
283    impl Mul<f64> for FourierCurve{
284        type Output = FourierCurve;
285        fn mul(self, rhs: f64) -> Self::Output {
286            let mut f = self;
287            for a in f.curves.iter_mut(){
288                *a =  *a * rhs;
289            }
290            f
291        }
292    }
293    
294    impl Add<FourierCurve> for FourierCurve{
295        type Output = FourierCurve;
296        fn add(self, rhs: FourierCurve) -> Self::Output {
297            let mut f = self;
298            for c in rhs.curves{
299                f = f + c;
300            }
301            f
302        }
303    }
304    impl Add<Curve> for FourierCurve{
305        type Output = FourierCurve;
306        fn add(self, rhs: Curve) -> Self::Output {
307            let mut f = self;
308            let mut is_added = false;
309            for c in f.curves.iter_mut(){
310                match *c + rhs{
311                    Some(curve)=>{
312                        *c = curve;
313                        is_added = true;
314                    },
315                    None=>{},
316                }
317            }
318            if !is_added{
319                f.curves.push(rhs);
320            }
321            f
322        }
323    }
324    impl Sub<Curve> for FourierCurve{
325        type Output = FourierCurve;
326        fn sub(self, rhs: Curve) -> Self::Output {
327            self + rhs * -1.
328        }
329    }
330    impl Sub<FourierCurve> for FourierCurve{
331        type Output = FourierCurve;
332        fn sub(self, rhs: FourierCurve) -> Self::Output {
333            self + rhs * -1.
334        }
335    }
336        
337
338}// pub mod curves
339
340pub mod functions{
341    use plotters::prelude::*;
342    use super::prelude::*;
343
344    use std::{error::Error, ops::{Sub, Add, Mul, Div}};
345
346    /// A Function is a list of Bounded Polynomials
347    #[derive(Debug, Clone, PartialEq)]
348    pub struct Function{
349        pub funcs:Vec<BoundedPolynomial>,
350    }
351    impl Function{
352        pub fn new()->Self{
353            Self{funcs:Vec::new()}
354        }
355    }
356    impl Bounded for Function{
357        fn in_bounds(self:&Self, x:f64) ->bool {
358            for p in &self.funcs{
359                if p.in_bounds(x){
360                    return true
361                }
362            }
363            false
364        }
365    }
366    impl Calculus for Function{
367        fn integrate(self: &Self) -> Self {
368            let mut f = Function::new();
369            for bp in &self.funcs{
370                f = (f + bp.integrate()).unwrap();
371            }
372            f
373        }
374        fn differenciate(self: &Self) ->Self {
375            let mut f = Function::new();
376            for bp in &self.funcs{
377                f = (f + bp.differenciate()).unwrap();
378            }
379            f
380        }
381    }
382    impl Ordinal for Function{
383        fn ord(self:&Self) ->f64 {
384            let mut max = f64::NEG_INFINITY;
385            for f in & self.funcs{
386                if f.ord()>max{
387                    max = f.ord();
388                }
389            }
390            max
391        }
392    }
393    impl Plottable for Function{
394        fn plot(self:&Self, output_file:&str, caption:&str, x_bound:(f32,f32), y_bound:(f32,f32), step:f32) ->Result<(),Box<dyn Error>> {
395            let root = BitMapBackend::new(output_file,(1080,920)).into_drawing_area();
396            root.fill(&WHITE)?;
397
398            let mut chart = ChartBuilder::on(&root)
399                .x_label_area_size(35)
400                .y_label_area_size(40)
401                .margin(5)
402                .caption(caption, ("sans-serif", 50.0))
403                .build_cartesian_2d(x_bound.0..x_bound.1, y_bound.0..y_bound.1)?;
404
405            chart.configure_mesh()
406                .x_labels(20)
407                .y_labels(10)
408                .disable_mesh()
409                .x_label_formatter(&|v| format!("{:.1}", v))
410                .y_label_formatter(&|v| format!("{:.1}", v))
411                .draw()?;
412                
413            let x_axis = (x_bound.0..x_bound.1).step(step);
414            chart.draw_series(LineSeries::new(x_axis.values().map(|x| (x, self.substitute(x as f64) as f32)), &RED))?;
415            //.label("Curve")
416            //.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
417            //chart.configure_series_labels().border_style(&BLACK).draw()?;
418
419            root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir");
420            println!("Result has been saved to {}", output_file);
421            Ok(())
422        }
423    }
424    impl Substitute for Function{
425        fn substitute(self:&Self, x:f64) ->f64 {
426            let mut ret = 0.;
427            for t in &self.funcs{
428                ret +=t.substitute(x);
429            }
430            ret
431        }
432    }
433
434    impl Add<BoundedPolynomial> for Function{
435        type Output = Option<Function>;
436        fn add(self, rhs: BoundedPolynomial) -> Self::Output {
437            let mut f = self;
438            if f.in_bounds(rhs.bounds.0) || f.in_bounds(rhs.bounds.0){
439                return None;
440            }
441            f.funcs.push(rhs);
442            Some(f)
443        }
444    }
445    // piggy back off Add
446    impl Sub<BoundedPolynomial> for Function{
447        type Output = Option<Function>;
448        fn sub(self, rhs: BoundedPolynomial) -> Self::Output {
449            self + rhs * -1.
450        }
451    }
452    impl Mul<Term> for Function{
453        type Output = Function;
454        fn mul(self, rhs: Term) -> Self::Output {
455            let mut f = Function::new();
456            for b in self.funcs{
457                f = (f + b * rhs).unwrap();
458            }
459            f
460        }
461    }
462    impl Mul<f64> for Function{
463        type Output = Function;
464        fn mul(self, rhs: f64) -> Self::Output {
465            let mut f = Function::new();
466            for b in self.funcs{
467                f = (f + b * rhs).unwrap();
468            }
469            f
470        }
471    }
472    impl Div<Term> for Function{
473        type Output = Function;
474        fn div(self, rhs: Term) -> Self::Output {
475            let mut f = Function::new();
476            for b in self.funcs{
477                f = (f + b / rhs).unwrap();
478            }
479            f
480        }
481    }
482    impl Div<f64> for Function{
483        type Output = Function;
484        fn div(self, rhs: f64) -> Self::Output {
485            let mut f = Function::new();
486            for b in self.funcs{
487                f = (f + b / rhs).unwrap();
488            }
489            f
490        }
491    }
492
493
494    /// A bounded polynomial contains a polynomial and bounds in which it is defined
495    #[derive(Debug, Clone, PartialEq)]
496    pub struct BoundedPolynomial{
497        pub poly:Polynomial,
498        pub bounds:(f64, f64),
499    }
500    impl BoundedPolynomial{
501        pub fn bounds_mut(self:&mut Self)-> &mut (f64, f64){
502            &mut self.bounds
503        }
504    }
505    impl Bounded for BoundedPolynomial{
506        fn in_bounds(self:&Self, x:f64)->bool{
507            self.bounds.0<=x && x< self.bounds.1
508        }
509    }
510    impl From<Polynomial> for BoundedPolynomial{
511        fn from(poly: Polynomial) -> Self {
512            Self{poly, bounds:(0.,10.)}
513        }
514    }
515    impl Ordinal for BoundedPolynomial{
516        fn ord(self:&Self) ->f64 {
517            self.poly.ord()
518        }
519    }
520    impl Calculus for BoundedPolynomial{
521        fn differenciate(self: &Self) ->Self {
522            Self{
523                poly : self.poly.differenciate(),
524                bounds: self.bounds,
525            }
526        }
527        fn integrate(self: &Self) -> Self {
528            Self{
529                poly : self.poly.integrate(),
530                bounds: self.bounds,
531            }
532        }
533    }
534    impl Substitute for BoundedPolynomial{
535        fn substitute(self:&Self, x:f64) ->f64 {
536            if self.bounds.0<x && self.bounds.1>x{
537                return self.poly.substitute(x);
538            }
539            0.
540        }
541    }
542
543    impl Add<Term> for BoundedPolynomial{
544        type Output = BoundedPolynomial;
545        fn add(self, rhs: Term) -> Self::Output {
546            Self::Output{
547                poly: self.poly + rhs,
548                bounds: self.bounds,
549            }
550        }
551    }
552    impl Sub<Term> for BoundedPolynomial{
553        type Output = BoundedPolynomial;
554        fn sub(self, rhs: Term) -> Self::Output {
555            Self::Output{
556                poly: self.poly - rhs,
557                bounds: self.bounds,
558            }
559        }
560    }
561
562    impl Mul<f64> for BoundedPolynomial{
563        type Output = BoundedPolynomial;
564        fn mul(self, rhs: f64) -> Self::Output {
565            Self::Output{
566                poly: self.poly * rhs,
567                bounds: self.bounds,
568            }
569        }
570    }
571    impl Mul<Term> for BoundedPolynomial{
572        type Output = BoundedPolynomial;
573        fn mul(self, rhs: Term) -> Self::Output {
574            Self::Output{
575                poly: self.poly * rhs,
576                bounds: self.bounds,
577            }
578        }
579    }
580
581
582    impl Div<f64> for BoundedPolynomial{
583        type Output = BoundedPolynomial;
584        fn div(self, rhs: f64) -> Self::Output {
585            Self::Output{
586                poly: self.poly / rhs,
587                bounds: self.bounds,
588            }
589        }
590    }
591    impl Div<Term> for BoundedPolynomial{
592        type Output = BoundedPolynomial;
593        fn div(self, rhs: Term) -> Self::Output {
594            Self::Output{
595                poly: self.poly / rhs,
596                bounds: self.bounds,
597            }
598        }
599    }
600    
601    
602    #[derive(Debug, Clone)]
603    /// contains a list of terms
604    pub struct Polynomial{
605        pub terms:Vec<Term>,
606    }
607    impl Polynomial{
608        pub fn new()->Self{
609            Self{terms: Vec::new()}
610        }
611    }
612    impl Ordinal for Polynomial{
613        fn ord(self:&Self) ->f64 {
614            let mut max = f64::NEG_INFINITY;
615            for t in &self.terms{
616                if t.pow>max{
617                    max = t.pow;
618                }
619            }
620            max
621        }
622    }
623    impl Calculus for Polynomial{
624        fn integrate(self: &Self) -> Self {
625            let mut p = Polynomial::new();
626            for t in &self.terms{
627                p = p + t.integrate();
628            }
629            p
630        }
631        fn differenciate(self: &Self) ->Self {
632            let mut p = Polynomial::new();
633            for t in &self.terms{
634                p = p + t.differenciate();
635            }
636            p
637        }
638    }
639
640    impl Substitute for Polynomial{
641        fn substitute(self:&Self, x:f64) ->f64 {
642            let mut ret = 0.;
643            for t in &self.terms{
644                ret +=t.substitute(x);
645            }
646            ret
647        }
648    }
649    impl PartialEq for Polynomial{
650        fn eq(&self, other: &Self) -> bool {
651            for a in &self.terms{
652                if !other.terms.contains(a){
653                    return false
654                }
655            }
656            true
657        }
658    }
659    
660    impl Add<Polynomial> for Polynomial{
661        type Output = Polynomial;
662        fn add(self, rhs: Polynomial) -> Self::Output {
663            let mut poly = self;
664            for t in rhs.terms{
665                poly = poly + t;
666            }
667            poly
668        }
669    }
670    impl Add<Term> for Polynomial{
671        type Output = Polynomial;
672        fn add(self, rhs: Term) -> Self::Output {
673            let mut poly = self;
674            let mut is_added = false;
675            for t in poly.terms.iter_mut(){
676                match *t + rhs{
677                    Some(term)=>{
678                        *t = term;
679                        is_added = true;
680                    },
681                    None=>{},
682                }
683            }
684            if !is_added{
685                poly.terms.push(rhs);
686            }
687            poly
688        }
689    }
690    impl Sub<Term> for Polynomial{
691        type Output = Polynomial;
692        fn sub(self, rhs: Term) -> Self::Output {
693            self + rhs * -1.
694        }
695    }
696    impl Sub<Polynomial> for Polynomial{
697        type Output = Polynomial;
698        fn sub(self, rhs: Polynomial) -> Self::Output {
699            self + rhs * -1.
700        }
701    }
702    impl Mul<f64> for Polynomial{
703        type Output = Polynomial;
704        fn mul(self, rhs: f64) -> Self::Output {
705            let mut p = Polynomial::new();
706            for t in self.terms{
707                p = p + t*rhs;
708            }
709            p
710        }
711    }
712    impl Mul<Term> for Polynomial{
713        type Output = Polynomial;
714        fn mul(self, rhs: Term) -> Self::Output {
715            let mut p = Polynomial::new();
716            for t in self.terms{
717                p = p + t*rhs;
718            }
719            p
720        }
721    }
722    impl Div<f64> for Polynomial{
723        type Output = Polynomial;
724        fn div(self, rhs: f64) -> Self::Output {
725            let mut p = Polynomial::new();
726            for t in self.terms{
727                p = p + t/rhs;
728            }
729            p
730        }
731    }
732    impl Div<Term> for Polynomial{
733        type Output = Polynomial;
734        fn div(self, rhs: Term) -> Self::Output {
735            let mut p = Polynomial::new();
736            for t in self.terms{
737                p = p + t/rhs;
738            }
739            p
740        }
741    }
742
743    /// A term is in the form
744    /// (coef * x ^ pow)
745    #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
746    pub struct Term{
747        pub coef:f64,
748        pub pow:f64
749    }
750    impl Term{
751        pub fn new(coef:f64, pow:f64)->Self{
752            Self{pow, coef}
753        }
754    }
755    impl Substitute for Term{
756        fn substitute(self:&Self, x:f64)->f64{
757            self.coef* x.powf(self.pow)
758        }
759    }
760    impl Calculus for Term{
761        fn differenciate(self: &Self) ->Self {
762            Self{
763                coef: self.coef*self.pow,
764                pow: self.pow-1.
765            }
766        }
767        fn integrate(self: &Self) -> Self {
768            Self{
769                coef: self.coef/(self.pow+1.),
770                pow: self.pow+1.,
771            }
772        }
773    }
774    /// Subtracting and Adding Terms can only work iff the pow is the same
775    impl Sub<Term> for Term{
776        type Output = Option<Term>;
777        fn sub(self, rhs: Self) -> Self::Output {
778            if self.pow == rhs.pow{
779                return Some(Self{
780                    coef: self.coef-rhs.coef,
781                    pow:self.pow,
782                })
783            }
784            None
785        }
786    }
787    impl Add<Term> for Term{
788        type Output = Option<Term>;
789        fn add(self, rhs: Self) -> Self::Output {
790            if self.pow == rhs.pow{
791                return Some(Self{
792                    coef: self.coef+rhs.coef,
793                    pow:self.pow,
794                })
795            }
796            None
797        }
798    }
799    impl Mul<Term> for Term{
800        type Output = Term;
801        fn mul(self, rhs: Term) -> Self::Output {
802            Self::Output{
803                coef:self.coef*rhs.coef,
804                pow:self.pow+rhs.pow,
805            }
806        }
807    }
808    impl Div<Term> for Term{
809        type Output = Term;
810        fn div(self, rhs: Term) -> Self::Output {
811            Self::Output{
812                coef:self.coef/rhs.coef,
813                pow:self.pow-rhs.pow,
814            }
815        }
816    }
817    impl Mul<f64> for Term{
818        type Output = Term;
819        fn mul(self, rhs: f64) -> Self::Output {
820            Self::Output{
821                coef: self.coef*rhs,
822                pow: self.pow,
823            }
824        }
825    }
826    impl Div<f64> for Term{
827        type Output = Term;
828        fn div(self, rhs: f64) -> Self::Output {
829            Self::Output{
830                coef: self.coef/rhs,
831                pow: self.pow,
832            }
833        }
834    }
835    
836}
837
838
839
840
841
842#[cfg(test)]
843mod tests{
844    use crate::{prelude::*, functions::*, curves::{*, Type::*}};
845
846    mod test_plots{
847        use super::*;
848
849        #[test]
850        fn first(){
851            let mut curve = FourierCurve::new();
852            curve.push(Curve::new(1.,1., Sine));
853            curve.push(Curve::new(0.5,3., Sine));
854            curve.push(Curve::new(1./4.,5., Sine));
855            curve.push(Curve::new(1./8., 7., Sine));
856            
857            curve.plot("plotters-doc-data/first_test.png","test 1", (0.0,20.0), (-10.0, 20.0), 0.01).unwrap();
858
859
860        }
861        #[test]
862        fn square(){
863            let mut curve = FourierCurve::new();
864            curve.push(Curve::new(4.0,1., Sine));
865            curve.push(Curve::new(4./3.,3.0, Sine));
866            curve.push(Curve::new(4./5.,5.0,Sine));
867            curve.push(Curve::new(4./7.,7., Sine));
868        
869            curve.plot("plotters-doc-data/square.png","square", (0.0,20.0), (-10.0, 20.0), 0.01).unwrap();
870
871
872        }
873        #[test]
874        fn saw_tooth(){
875            let mut curve = FourierCurve::new();
876            curve.push(Curve::new(-2.,1., Sine));
877            curve.push(Curve::new(1.,2., Sine));
878            curve.push(Curve::new(-2./3.,3., Sine));
879            curve.push(Curve::new(0.5, 4., Sine));
880
881
882            curve.plot("plotters-doc-data/saw_tooth.png","Saw Tooth", (0.0,20.0), (-10.0, 20.0), 0.01).unwrap();
883
884
885        }
886    } // mod test_plots
887    mod test_function{
888        use super::*;
889        #[test]
890        fn test_functions(){
891            let mut curve = Function::new();
892            curve = (curve +BoundedPolynomial{
893                poly:Polynomial{
894                    terms:vec![Term::new(1., 1.), Term::new(2., 2.), Term::new(3., 3.)]
895                }, 
896                bounds:(-1000., 1000.),
897            }).unwrap();
898            curve.plot("plotters-doc-data/test_func.png", "Test Function", (-100.,100.), (-1000.,1000.), 0.01).unwrap();
899        }
900        #[test]
901        fn function_binary(){
902            // Polynomial tests
903            let mut p = Polynomial::new();
904
905            // add term to polynomial
906            p = p + Term::new(1., 1.);
907            assert_eq!(
908                p, 
909                Polynomial{
910                    terms:vec!(
911                        Term::new(1., 1.),
912                    )
913                }
914            );
915            // add another term with same pow
916            p = p + Term::new(2., 1.);
917            assert_eq!(
918                p, 
919                Polynomial{
920                    terms:vec!(Term::new(3., 1.))
921                }
922            );
923            // add another term with a differnent pow
924            p = p + Term::new(2., 2.) + Term::new(3., 3.);
925            assert_eq!(p, 
926                Polynomial{
927                    terms:vec!(
928                        Term::new(3., 3.),
929                        Term::new(3., 1.),
930                        Term::new(2.,2.),
931                    )
932                }
933            );
934            // Term tests
935            let t = Term::new(1., 1.);
936            
937            // Term op Term tests
938            // add
939            assert_eq!(t + Term::new(2., 1.), Some(Term::new(3., 1.)));
940            assert_eq! (t + Term::new(2., 2.), None);
941            // sub
942            assert_eq!(t-Term::new(0.5, 1.), Some(Term::new(0.5, 1.)));
943            assert_eq!(t-Term::new(2., 1.), Some(Term::new(-1., 1.)));
944
945            // Term op f64 tests
946            // mul
947            assert_eq!(t * 2. , Term::new(2., 1.));
948            // div
949            assert_eq!(t / 5., Term::new(1./5., 1.));
950
951            // Term op Term tests
952            // mul
953            assert_eq!(t * Term::new(2., 1.), Term::new(2., 2.));
954            assert_eq!(t * Term::new(3., 2.), Term::new(3., 3.));
955            // div
956            assert_eq!(t / Term::new(3., 2.), Term::new(1./3., -1.));
957        }
958        #[test]
959        fn test_bounds(){
960            let mut bp = BoundedPolynomial::from(Polynomial{
961                terms: vec!(
962                    Term::new(1.,2.),
963                    Term::new(2.,3.),
964                )
965            });
966            assert!(bp.in_bounds(-1.) == false);
967            assert!(bp.in_bounds(5.) == true);
968            assert!(bp.in_bounds(11.) == false);
969
970            let b = bp.bounds_mut();
971            b.0 = -10.0;
972            
973            assert!(bp.in_bounds(-1.) == true);
974            assert!(bp.in_bounds(5.) == true);
975            assert!(bp.in_bounds(11.) == false);
976
977            assert!(bp.in_bounds(-10.) == true);
978        
979            assert!(bp.in_bounds(10.) == false);
980
981            let mut f = Function::new();
982            f = (f + 
983                BoundedPolynomial{
984                    poly : Polynomial{
985                        terms: vec!(
986                            Term::new(3., 2.),
987                        )
988                    },
989                bounds: (0., 10.),
990            }).unwrap();
991            assert!(
992                (f.clone() + BoundedPolynomial{
993                    poly : Polynomial{
994                        terms: vec!(
995                            Term::new(3., 2.),
996                        )
997                    },
998                bounds: (9., 20.),
999            }) == None);
1000
1001            assert!((f + BoundedPolynomial{
1002                    poly : Polynomial{
1003                        terms: vec!(
1004                            Term::new(3., 2.),
1005                        )
1006                    },
1007                bounds: (10., 20.),
1008            }) == Some( Function{
1009                    funcs: vec!(
1010                        BoundedPolynomial{
1011                            poly : Polynomial{
1012                                terms: vec!(
1013                                    Term::new(3., 2.),
1014                                )
1015                            },
1016                            bounds: (0., 10.),
1017                        },
1018                        BoundedPolynomial{
1019                            poly : Polynomial{
1020                                terms: vec!(
1021                                    Term::new(3., 2.),
1022                                )
1023                            },
1024                            bounds: (10., 20.),
1025                        }
1026                    )
1027                }
1028
1029            ));
1030
1031        }
1032        
1033        #[test]
1034        fn test_calculus(){
1035            let t = Term::new(2., 3.);
1036            assert_eq!(
1037                t.integrate(),
1038                Term::new(2./4., 4.)
1039            );
1040            assert_eq!(
1041                t.differenciate(),
1042                Term::new(2.*3., 2.)
1043            );
1044
1045
1046            let mut p = Polynomial{
1047                terms : vec!(
1048                    Term::new(2., 3.)
1049                )
1050            };
1051            assert_eq!(
1052                p.integrate(),
1053                Polynomial{
1054                    terms : vec!(
1055                        Term::new(2., 3.).integrate(),
1056                    )
1057                }
1058            );
1059            p = p + Term::new(3., 5.);
1060
1061            assert_eq!(
1062                p.integrate(),
1063                Polynomial{
1064                    terms : vec!(
1065                        Term::new(2., 3.).integrate(),
1066                        Term::new(3., 5.).integrate(),
1067                    )
1068                }
1069            );
1070
1071            let mut f = Function::new();
1072            f =( f +
1073                BoundedPolynomial{
1074                    poly: Polynomial{
1075                        terms: vec!(
1076                            Term::new(2., 3.),
1077                        )
1078                    }, 
1079                    bounds: (0., 10.),
1080                }
1081            ).unwrap();
1082
1083            assert_eq!(
1084                f.integrate(),
1085                Function{
1086                    funcs: vec!(
1087                        BoundedPolynomial{
1088                            poly: Polynomial{
1089                                terms: vec!(
1090                                    Term::new(2., 3.).integrate(),
1091                                )
1092                            }, 
1093                            bounds: (0., 10.),
1094                        }
1095                    )
1096                }
1097            );
1098
1099            f = ( f +
1100                BoundedPolynomial{
1101                    poly: Polynomial{
1102                        terms: vec!(
1103                            Term::new(2., 4.),
1104                        )
1105                    }, 
1106                    bounds: (10., 20.),
1107                }
1108            ).unwrap();
1109
1110            assert_eq!(
1111                f.integrate(),
1112                Function{
1113                    funcs: vec!(
1114                        BoundedPolynomial{
1115                            poly: Polynomial{
1116                                terms: vec!(
1117                                    Term::new(2., 3.).integrate(),
1118                                )
1119                            }, 
1120                            bounds: (0., 10.),
1121                        },
1122                        BoundedPolynomial{
1123                            poly: Polynomial{
1124                                terms: vec!(
1125                                    Term::new(2., 4.).integrate(),
1126                                )
1127                            }, 
1128                            bounds: (10., 20.),
1129                        }
1130                    )
1131                }
1132            );
1133        }
1134    } // mod test_function
1135    mod test_curves{
1136        use super::*;
1137        #[test]
1138        fn curves_binary(){
1139            let c = Curve::new(1., 1.,  Sine);
1140            assert_eq!(
1141                c + Curve::new(  2.,  1.,  Sine) ,
1142                Some(Curve::new(3.,  1.,  Sine))
1143            );
1144
1145            assert_eq!(
1146                c + Curve::new(  2.,  1.,  Cosine) , 
1147                None
1148            );
1149
1150            assert_eq!(
1151                c + Curve::new(  2.,  2.,  Sine) , 
1152                None
1153            );
1154
1155            assert_eq!(
1156                c + Curve::new(  2.,  2.,  Cosine) , 
1157                None
1158            );
1159
1160            let mut f = FourierCurve{
1161                curves: vec!(
1162                    Curve::new(1., 1., Sine),
1163                )
1164            };
1165
1166            f = f + Curve::new(2., 1., Sine);
1167            assert_eq!(
1168                f ,
1169                FourierCurve{
1170                    curves: vec!(
1171                        Curve::new(3., 1., Sine),
1172                    )
1173                }
1174            );
1175            f = f + Curve::new(2., 2., Sine);
1176            assert_eq!(
1177                f,
1178                FourierCurve{
1179                    curves: vec!(
1180                        Curve::new(3., 1., Sine),
1181                        Curve::new(2., 2., Sine),
1182                    )
1183                }
1184            );
1185        }// fn curves_binary
1186
1187        #[test]
1188        fn curves_calculus(){
1189            let c = Curve::new(2., 3., Sine);
1190            // Sine integrates to - Cosine
1191            assert_eq!(
1192                c.integrate(),
1193                Curve::new(-2./3., 3., Cosine)
1194            );
1195
1196            // Sine differentiates to Cosine
1197            assert_eq!(
1198                c.differenciate(),
1199                Curve::new(2.*3., 3., Cosine)
1200            );
1201
1202            let f = FourierCurve{
1203                curves:vec!(
1204                    Curve::new(2., 3., Sine)
1205                )
1206            };
1207            assert_eq!(
1208                f.integrate(),
1209                FourierCurve{
1210                    curves:vec!(
1211                        Curve::new(2., 3., Sine).integrate()
1212                    )
1213                }
1214            );
1215
1216        }
1217    } // mod test_curves
1218}// mod tests