1use std::fmt;
2use std::ops;
3
4pub fn deg(mut degrees: i32) -> Angle {
17 while degrees < 0 {
18 degrees += 360;
19 }
20
21 while degrees >= 360 {
22 degrees -= 360;
23 }
24
25 Angle::new(degrees as u16)
26}
27
28#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
29pub struct Angle {
32 degrees: u16,
33}
34
35impl Angle {
36 pub fn new(degrees: u16) -> Self {
37 assert!(degrees < 360, "invalid angle");
38
39 Angle { degrees }
40 }
41
42 pub fn degrees(self) -> u16 {
43 self.degrees
44 }
45}
46
47impl fmt::Display for Angle {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 write!(f, "{}deg", self.degrees)
50 }
51}
52
53impl ops::Neg for Angle {
54 type Output = Angle;
55
56 fn neg(self) -> Angle {
57 Angle {
58 degrees: (360 - self.degrees) % 360,
59 }
60 }
61}
62
63impl ops::Add for Angle {
64 type Output = Angle;
65
66 fn add(self, other: Angle) -> Angle {
67 let temp: u32 = self.degrees as u32 + other.degrees as u32;
68 let degrees: u16 = (temp % 360) as u16;
69
70 Angle { degrees }
71 }
72}
73
74impl ops::Sub for Angle {
75 type Output = Angle;
76
77 fn sub(self, other: Angle) -> Angle {
78 self + (-other)
79 }
80}
81
82impl ops::Mul for Angle {
83 type Output = Angle;
84
85 fn mul(self, other: Angle) -> Angle {
86 let temp: u32 = self.degrees as u32 * other.degrees as u32;
87 let degrees: u16 = (temp % 360) as u16;
88
89 Angle { degrees }
90 }
91}
92
93impl ops::Div for Angle {
94 type Output = Angle;
95
96 fn div(self, other: Angle) -> Angle {
97 if other.degrees == 0 {
98 panic!("Cannot divide by zero-valued `Angle`!");
99 }
100
101 let temp: u32 = self.degrees as u32 / other.degrees as u32;
102 let degrees: u16 = (temp % 360) as u16;
103
104 Angle { degrees }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use Angle;
111
112 #[test]
113 fn can_have_degrees() {
114 assert_eq!(Angle::new(30).degrees(), 30);
115 assert_eq!(Angle::new(47).degrees(), 47);
116 }
117
118 #[test]
119 fn can_display_angles() {
120 assert_eq!("30deg", format!("{}", Angle::new(30)));
121 assert_eq!("30deg", Angle::new(30).to_string());
122 }
123
124 #[test]
125 fn can_eq_angles() {
126 assert_eq!(Angle::new(30), Angle::new(30));
127 assert_ne!(Angle::new(30), Angle::new(47));
128 }
129
130 #[test]
131 fn can_ord_angles() {
132 assert_eq!(Angle::new(30) < Angle::new(47), true);
133 assert_eq!(Angle::new(47) < Angle::new(30), false);
134 assert_eq!(Angle::new(30) < Angle::new(30), false);
135
136 assert_eq!(Angle::new(30) <= Angle::new(47), true);
137 assert_eq!(Angle::new(47) <= Angle::new(30), false);
138 assert_eq!(Angle::new(30) <= Angle::new(30), true);
139
140 assert_eq!(Angle::new(30) > Angle::new(47), false);
141 assert_eq!(Angle::new(47) > Angle::new(30), true);
142 assert_eq!(Angle::new(30) > Angle::new(30), false);
143
144 assert_eq!(Angle::new(30) >= Angle::new(47), false);
145 assert_eq!(Angle::new(47) >= Angle::new(30), true);
146 assert_eq!(Angle::new(30) >= Angle::new(30), true);
147 }
148
149 #[test]
150 fn can_add_angles() {
151 assert_eq!(Angle::new(30) + Angle::new(47), Angle::new(77));
152 assert_eq!(Angle::new(47) + Angle::new(30), Angle::new(77));
153 assert_eq!(Angle::new(359) + Angle::new(1), Angle::new(0));
154 assert_eq!(
155 Angle::new(359) + Angle::new(359) + Angle::new(359),
156 Angle::new(357)
157 );
158 }
159
160 #[test]
161 fn can_sub_angles() {
162 assert_eq!(Angle::new(30) - Angle::new(47), Angle::new(343));
163 assert_eq!(Angle::new(47) - Angle::new(30), Angle::new(17));
164 assert_eq!(Angle::new(0) - Angle::new(1), Angle::new(359));
165 assert_eq!(
166 Angle::new(0) - Angle::new(359) - Angle::new(359) - Angle::new(359),
167 Angle::new(3)
168 );
169 }
170
171 #[test]
172 fn test_mul_angles() {
173 assert_eq!(Angle::new(30) * Angle::new(0), Angle::new(0));
174 assert_eq!(Angle::new(30) * Angle::new(1), Angle::new(30));
175 assert_eq!(Angle::new(30) * Angle::new(2), Angle::new(60));
176
177 assert_eq!(Angle::new(30) * Angle::new(12), Angle::new(0));
178 assert_eq!(Angle::new(30) * Angle::new(13), Angle::new(30));
179 assert_eq!(Angle::new(30) * Angle::new(100), Angle::new(120));
180
181 assert_eq!(Angle::new(47) * Angle::new(0), Angle::new(0));
182 assert_eq!(Angle::new(47) * Angle::new(1), Angle::new(47));
183 assert_eq!(Angle::new(47) * Angle::new(2), Angle::new(94));
184
185 assert_eq!(Angle::new(47) * Angle::new(8), Angle::new(16));
186 assert_eq!(Angle::new(47) * Angle::new(100), Angle::new(20));
187 }
188
189 #[test]
190 fn test_divide_angles() {
191 assert_eq!(Angle::new(30) / Angle::new(1), Angle::new(30));
192 assert_eq!(Angle::new(30) / Angle::new(2), Angle::new(15));
193
194 assert_eq!(Angle::new(180) / Angle::new(12), Angle::new(15));
195 assert_eq!(Angle::new(180) / Angle::new(2), Angle::new(90));
196 assert_eq!(Angle::new(180) / Angle::new(5), Angle::new(36));
197
198 assert_eq!(Angle::new(47) / Angle::new(2), Angle::new(23));
199 }
200}