ac_power/trig/newtypes/
cos.rs1use crate::trig::cos_sin;
17use crate::trig::Sin;
18use crate::trig::Theta;
19use core::convert::From;
20use core::ops::{Mul, Neg};
21use derive_more::{From, Into};
22
23#[derive(Debug, Copy, Clone, PartialEq, From, Into)]
25pub struct Cos(f32);
26
27impl Cos {
28 pub fn from_theta(theta: Theta) -> Self {
39 let (cos, _) = cos_sin(theta);
40 cos
41 }
42
43 pub fn from_degrees(degrees: f32) -> Self {
53 let theta = Theta::from_degrees(degrees);
54 Self::from_theta(theta)
55 }
56
57 pub fn from_radians(radians: f32) -> Self {
67 let theta = Theta::from_radians(radians);
68 Self::from_theta(theta)
69 }
70}
71
72impl Neg for Cos {
73 fn neg(self) -> Self {
74 Self(-self.0)
75 }
76 type Output = Self;
77}
78
79impl From<i32> for Cos {
80 fn from(item: i32) -> Self {
81 Self((item as f32) / 2147483648.)
82 }
83}
84
85impl Mul<Cos> for Cos {
86 fn mul(self, other: Cos) -> f32 {
87 self.0 * other.0
88 }
89 type Output = f32;
90}
91
92impl Mul<Sin> for Cos {
93 fn mul(self, rhs: Sin) -> f32 {
94 self.0 * rhs
95 }
96 type Output = f32;
97}
98
99#[cfg(test)]
100mod tests {
101
102 use super::*;
103 use approx::assert_abs_diff_eq;
104
105 use std::f32::consts::PI;
106
107 fn linspace(x0: f32, x1: f32, length: usize) -> Vec<f32> {
108 let dx = (x1 - x0) / ((length - 1) as f32);
109 let mut xs: Vec<f32> = vec![x0];
110 for index in 1..length {
111 xs.push(xs[index - 1] + dx);
112 }
113 xs
114 }
115
116 fn degrees_to_radians(degrees: f32) -> f32 {
117 2.0 * PI * (degrees / 360.0)
118 }
119
120 fn check_from_degrees(degrees: f32) {
121 let cos = Cos::from_degrees(degrees);
122 let radians = degrees_to_radians(degrees);
123 assert_abs_diff_eq!(f32::from(cos), radians.cos(), epsilon = 0.0001);
124 }
125
126 fn check_from_radians(radians: f32) {
127 let cos = Cos::from_radians(radians);
128 assert_abs_diff_eq!(f32::from(cos), radians.cos(), epsilon = 0.0001);
129 }
130
131 #[test]
132 fn constructors() {
133 let angles = linspace(-720.0, 720.0, 500);
134 for angle in angles.iter() {
135 check_from_degrees(*angle);
136 }
137
138 let angles = linspace(-4.0 * PI, 4.0 * PI, 100);
139 for angle in angles.iter() {
140 check_from_radians(*angle);
141 }
142 }
143
144 #[test]
145 fn conversions() {
146 let x = 0.707;
147 let cos = Cos::from(x);
148 assert_abs_diff_eq!(x, f32::from(cos), epsilon = 0.0001);
149 }
150
151 #[test]
152 fn arithmetic() {
153 let radians = 0.26;
154 let cos = Cos::from_radians(radians);
155 let x = 1.0;
156 assert_abs_diff_eq!(x * cos, x * radians.cos(), epsilon = 0.0001);
157 assert_abs_diff_eq!(cos * x, x * radians.cos(), epsilon = 0.0001);
158 assert_abs_diff_eq!(cos * cos, radians.cos() * radians.cos(), epsilon = 0.0001);
159 }
160}