1pub mod amount_of_substance_unit;
18pub mod electric_current_unit;
19pub mod length_unit;
20pub mod luminous_intensity_unit;
21pub mod mass_unit;
22pub mod temperature_unit;
23pub mod time_unit;
24
25use crate::complex_units::ComplexUnit;
26use crate::units::amount_of_substance_unit::AmountOfSubstanceUnit;
27use crate::units::electric_current_unit::ElectricCurrentUnit;
28use crate::units::length_unit::LengthUnit;
29use crate::units::luminous_intensity_unit::LuminousIntensityUnit;
30use crate::units::mass_unit::MassUnit;
31use crate::units::temperature_unit::TemperatureDeltaUnit;
32use crate::units::time_unit::TimeUnit;
33
34use std::cmp::Ordering;
35use std::fmt::Display;
36use std::ops;
37
38#[derive(Clone, Debug)]
39pub struct EngUnit {
40 pub value: f64,
41 pub amount_of_substance_count: i32,
42 pub amount_of_substance_unit: AmountOfSubstanceUnit,
43 pub electric_current_count: i32,
44 pub electric_current_unit: ElectricCurrentUnit,
45 pub length_count: i32,
46 pub length_unit: LengthUnit,
47 pub luminous_intensity_count: i32,
48 pub luminous_intensity_unit: LuminousIntensityUnit,
49 pub mass_count: i32,
50 pub mass_unit: MassUnit,
51 pub temperature_count: i32,
52 pub temperature_unit: TemperatureDeltaUnit,
53 pub time_count: i32,
54 pub time_unit: TimeUnit,
55 pub unit_numerator: Vec<ComplexUnit>,
56 pub unit_denominator: Vec<ComplexUnit>,
57}
58
59impl Default for EngUnit {
60 fn default() -> Self {
61 Self::new()
62 }
63}
64
65impl Display for EngUnit {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 if self.has_units() || self.has_custom_untits() {
68 write!(f, "{:.2} {}", self.value, self.unit_to_string())
69 } else {
70 write!(f, "{:.2}", self.value)
71 }
72 }
73}
74
75pub trait Convert<T> {
76 fn conversion_factor(from_unit: &T, to_unit: &T) -> f64;
77}
78
79pub trait IsEngUnitType {
80 fn is_amount_unit() -> bool {
81 false
82 }
83 fn is_electric_current_unit() -> bool {
84 false
85 }
86 fn is_length_unit() -> bool {
87 false
88 }
89 fn is_luminous_unit() -> bool {
90 false
91 }
92 fn is_mass_unit() -> bool {
93 false
94 }
95 fn is_temperature_unit() -> bool {
96 false
97 }
98 fn is_time_unit() -> bool {
99 false
100 }
101}
102
103impl EngUnit {
104 pub fn new() -> Self {
105 Self {
106 value: 1.0,
107 length_count: 0,
108 length_unit: LengthUnit::None,
109 time_count: 0,
110 time_unit: TimeUnit::None,
111 mass_count: 0,
112 mass_unit: MassUnit::None,
113 temperature_count: 0,
114 temperature_unit: TemperatureDeltaUnit::None,
115 electric_current_count: 0,
116 electric_current_unit: ElectricCurrentUnit::None,
117 luminous_intensity_count: 0,
118 luminous_intensity_unit: LuminousIntensityUnit::None,
119 amount_of_substance_count: 0,
120 amount_of_substance_unit: AmountOfSubstanceUnit::None,
121 unit_numerator: Vec::new(),
122 unit_denominator: Vec::new(),
123 }
124 }
125
126 fn has_custom_untits(&self) -> bool {
127 self.unit_numerator.len() > 0 || self.unit_denominator.len() > 0
128 }
129
130 fn to_amount_unit<
131 T: Into<AmountOfSubstanceUnit>
132 + Into<ElectricCurrentUnit>
133 + Into<LengthUnit>
134 + Into<LuminousIntensityUnit>
135 + Into<MassUnit>
136 + Into<TemperatureDeltaUnit>
137 + Into<TimeUnit>,
138 >(
139 unit: T,
140 ) -> AmountOfSubstanceUnit {
141 unit.into()
142 }
143 fn to_electric_unit<
144 T: Into<AmountOfSubstanceUnit>
145 + Into<ElectricCurrentUnit>
146 + Into<LengthUnit>
147 + Into<LuminousIntensityUnit>
148 + Into<MassUnit>
149 + Into<TemperatureDeltaUnit>
150 + Into<TimeUnit>,
151 >(
152 unit: T,
153 ) -> ElectricCurrentUnit {
154 unit.into()
155 }
156 fn to_length_unit<
157 T: Into<AmountOfSubstanceUnit>
158 + Into<ElectricCurrentUnit>
159 + Into<LengthUnit>
160 + Into<LuminousIntensityUnit>
161 + Into<MassUnit>
162 + Into<TemperatureDeltaUnit>
163 + Into<TimeUnit>,
164 >(
165 unit: T,
166 ) -> LengthUnit {
167 unit.into()
168 }
169 fn to_luminous_unit<
170 T: Into<AmountOfSubstanceUnit>
171 + Into<ElectricCurrentUnit>
172 + Into<LengthUnit>
173 + Into<LuminousIntensityUnit>
174 + Into<MassUnit>
175 + Into<TemperatureDeltaUnit>
176 + Into<TimeUnit>,
177 >(
178 unit: T,
179 ) -> LuminousIntensityUnit {
180 unit.into()
181 }
182 fn to_mass_unit<
183 T: Into<AmountOfSubstanceUnit>
184 + Into<ElectricCurrentUnit>
185 + Into<LengthUnit>
186 + Into<LuminousIntensityUnit>
187 + Into<MassUnit>
188 + Into<TemperatureDeltaUnit>
189 + Into<TimeUnit>,
190 >(
191 unit: T,
192 ) -> MassUnit {
193 unit.into()
194 }
195 fn to_temperature_unit<
196 T: Into<AmountOfSubstanceUnit>
197 + Into<ElectricCurrentUnit>
198 + Into<LengthUnit>
199 + Into<LuminousIntensityUnit>
200 + Into<MassUnit>
201 + Into<TemperatureDeltaUnit>
202 + Into<TimeUnit>,
203 >(
204 unit: T,
205 ) -> TemperatureDeltaUnit {
206 unit.into()
207 }
208
209 fn to_time_unit<
210 T: Into<AmountOfSubstanceUnit>
211 + Into<ElectricCurrentUnit>
212 + Into<LengthUnit>
213 + Into<LuminousIntensityUnit>
214 + Into<MassUnit>
215 + Into<TemperatureDeltaUnit>
216 + Into<TimeUnit>,
217 >(
218 unit: T,
219 ) -> TimeUnit {
220 unit.into()
221 }
222
223 pub fn convert<
224 T: IsEngUnitType
225 + Into<AmountOfSubstanceUnit>
226 + Into<ElectricCurrentUnit>
227 + Into<LengthUnit>
228 + Into<LuminousIntensityUnit>
229 + Into<MassUnit>
230 + Into<TemperatureDeltaUnit>
231 + Into<TimeUnit>,
232 >(
233 &self,
234 to_unit: T,
235 ) -> Self {
236 let mut new_unit = self.clone();
237 if T::is_amount_unit() {
238 let from_unit = &self.amount_of_substance_unit;
239 let to_unit = EngUnit::to_amount_unit(to_unit);
240 let mut conversion_factor =
241 AmountOfSubstanceUnit::conversion_factor(from_unit, &to_unit);
242 conversion_factor = f64::powf(conversion_factor, self.amount_of_substance_count as f64);
243 match self.amount_of_substance_count.cmp(&0) {
244 Ordering::Greater => {
245 new_unit.value *= conversion_factor;
246 }
247 Ordering::Less => {
248 new_unit.value /= conversion_factor;
249 }
250 Ordering::Equal => {}
251 }
252 new_unit.amount_of_substance_unit = to_unit;
253 } else if T::is_electric_current_unit() {
254 let from_unit = &self.electric_current_unit;
255 let to_unit = EngUnit::to_electric_unit(to_unit);
256 let mut conversion_factor = ElectricCurrentUnit::conversion_factor(from_unit, &to_unit);
257 conversion_factor = f64::powf(conversion_factor, self.electric_current_count as f64);
258 match self.electric_current_count.cmp(&0) {
259 Ordering::Greater => {
260 new_unit.value *= conversion_factor;
261 }
262 Ordering::Less => {
263 new_unit.value /= conversion_factor;
264 }
265 Ordering::Equal => {}
266 }
267 new_unit.electric_current_unit = to_unit;
268 } else if T::is_length_unit() {
269 let from_unit = &self.length_unit;
270 let to_unit = EngUnit::to_length_unit(to_unit);
271 let mut conversion_factor = LengthUnit::conversion_factor(from_unit, &to_unit);
272 conversion_factor = f64::powf(conversion_factor, self.length_count as f64);
273 match self.length_count.cmp(&0) {
274 Ordering::Greater => {
275 new_unit.value *= conversion_factor;
276 }
277 Ordering::Less => {
278 new_unit.value /= conversion_factor;
279 }
280 Ordering::Equal => {}
281 }
282 new_unit.length_unit = to_unit;
283 } else if T::is_luminous_unit() {
284 let from_unit = &self.luminous_intensity_unit;
285 let to_unit = EngUnit::to_luminous_unit(to_unit);
286 let mut conversion_factor =
287 LuminousIntensityUnit::conversion_factor(from_unit, &to_unit);
288 conversion_factor = f64::powf(conversion_factor, self.luminous_intensity_count as f64);
289 match self.luminous_intensity_count.cmp(&0) {
290 Ordering::Greater => {
291 new_unit.value *= conversion_factor;
292 }
293 Ordering::Less => {
294 new_unit.value /= conversion_factor;
295 }
296 Ordering::Equal => {}
297 }
298 new_unit.luminous_intensity_unit = to_unit;
299 } else if T::is_mass_unit() {
300 let from_unit = &self.mass_unit;
301 let to_unit = EngUnit::to_mass_unit(to_unit);
302 let mut conversion_factor = MassUnit::conversion_factor(from_unit, &to_unit);
303 conversion_factor = f64::powf(conversion_factor, self.mass_count as f64);
304 match self.mass_count.cmp(&0) {
305 Ordering::Greater => {
306 new_unit.value *= conversion_factor;
307 }
308 Ordering::Less => {
309 new_unit.value /= conversion_factor;
310 }
311 Ordering::Equal => {}
312 }
313 new_unit.mass_unit = to_unit;
314 } else if T::is_temperature_unit() {
315 let from_unit = &self.temperature_unit;
316 let to_unit = EngUnit::to_temperature_unit(to_unit);
317 let mut conversion_factor =
318 TemperatureDeltaUnit::conversion_factor(from_unit, &to_unit);
319 conversion_factor = f64::powf(conversion_factor, self.temperature_count as f64);
320 match self.temperature_count.cmp(&0) {
321 Ordering::Greater => {
322 new_unit.value *= conversion_factor;
323 }
324 Ordering::Less => {
325 new_unit.value /= conversion_factor;
326 }
327 Ordering::Equal => {}
328 }
329 new_unit.temperature_unit = to_unit;
330 } else if T::is_time_unit() {
331 let from_unit = &self.time_unit;
332 let to_unit = EngUnit::to_time_unit(to_unit);
333 let conversion_factor = TimeUnit::conversion_factor(from_unit, &to_unit);
334 new_unit.value *= f64::powf(conversion_factor, self.time_count as f64);
335 match self.time_count.cmp(&0) {
336 Ordering::Greater => {
337 new_unit.value *= conversion_factor;
338 }
339 Ordering::Less => {
340 new_unit.value /= conversion_factor;
341 }
342 Ordering::Equal => {}
343 }
344 new_unit.time_unit = to_unit;
345 }
346 new_unit
347 }
348
349 fn has_units(&self) -> bool {
350 if self.length_count != 0 {
351 return true;
352 }
353 if self.time_count != 0 {
354 return true;
355 }
356 if self.mass_count != 0 {
357 return true;
358 }
359 if self.temperature_count != 0 {
360 return true;
361 }
362 if self.electric_current_count != 0 {
363 return true;
364 }
365 if self.luminous_intensity_count != 0 {
366 return true;
367 }
368 if self.amount_of_substance_count != 0 {
369 return true;
370 }
371 false
372 }
373
374 pub fn unit_to_string(&self) -> String {
375 let mut s_numerator: Vec<String> = Vec::new();
376 let mut s_denominator: Vec<String> = Vec::new();
377
378 for u in &self.unit_numerator {
379 s_numerator.push(u.unit_to_string())
380 }
381
382 if self.amount_of_substance_count >= 2 {
383 let s = format!(
384 "{}^{}",
385 self.amount_of_substance_unit.to_string(),
386 self.amount_of_substance_count
387 );
388 s_numerator.push(s);
389 } else if self.amount_of_substance_count == 1 {
390 let s = self.amount_of_substance_unit.to_string();
391 s_numerator.push(s.to_string());
392 }
393 if self.electric_current_count >= 2 {
394 let s = format!(
395 "{}^{}",
396 self.electric_current_unit.to_string(),
397 self.electric_current_count
398 );
399 s_numerator.push(s);
400 } else if self.electric_current_count == 1 {
401 let s = self.electric_current_unit.to_string();
402 s_numerator.push(s.to_string());
403 }
404 if self.mass_count >= 2 {
405 let s = format!("{}^{}", self.mass_unit.to_string(), self.mass_count);
406 s_numerator.push(s);
407 } else if self.mass_count == 1 {
408 let s = self.mass_unit.to_string();
409 s_numerator.push(s.to_string());
410 }
411 if self.length_count >= 2 {
412 let s = format!("{}^{}", self.length_unit.to_string(), self.length_count);
413 s_numerator.push(s);
414 } else if self.length_count == 1 {
415 let s = self.length_unit.to_string();
416 s_numerator.push(s.to_string());
417 }
418 if self.luminous_intensity_count >= 2 {
419 let s = format!(
420 "{}^{}",
421 self.luminous_intensity_unit.to_string(),
422 self.luminous_intensity_count
423 );
424 s_numerator.push(s);
425 } else if self.luminous_intensity_count == 1 {
426 let s = self.luminous_intensity_unit.to_string();
427 s_numerator.push(s.to_string());
428 }
429 if self.time_count >= 2 {
430 let s = format!("{}^{}", self.time_unit.to_string(), self.time_count);
431 s_numerator.push(s);
432 } else if self.time_count == 1 {
433 let s = self.time_unit.to_string();
434 s_numerator.push(s.to_string());
435 }
436 if self.temperature_count >= 2 {
437 let s = format!(
438 "{}^{}",
439 self.temperature_unit.to_string(),
440 self.temperature_count
441 );
442 s_numerator.push(s);
443 } else if self.temperature_count == 1 {
444 let s = self.temperature_unit.to_string();
445 s_numerator.push(s.to_string());
446 }
447
448 for u in &self.unit_denominator {
450 s_denominator.push(u.unit_to_string())
451 }
452 if self.amount_of_substance_count <= -2 {
453 let s = format!(
454 "{}^{}",
455 self.amount_of_substance_unit.to_string(),
456 self.amount_of_substance_count
457 );
458 s_denominator.push(s);
459 } else if self.amount_of_substance_count == -1 {
460 let s = self.amount_of_substance_unit.to_string();
461 s_denominator.push(s.to_string());
462 }
463
464 if self.electric_current_count <= -2 {
465 let s = format!(
466 "{}^{}",
467 self.electric_current_unit.to_string(),
468 self.electric_current_count
469 );
470 s_denominator.push(s);
471 } else if self.electric_current_count == -1 {
472 let s = self.electric_current_unit.to_string();
473 s_denominator.push(s.to_string());
474 }
475
476 if self.length_count <= -2 {
477 let s = format!("{}^{}", self.length_unit.to_string(), self.length_count);
478 s_denominator.push(s);
479 } else if self.length_count == -1 {
480 let s = self.length_unit.to_string();
481 s_denominator.push(s.to_string());
482 }
483
484 if self.luminous_intensity_count <= -2 {
485 let s = format!(
486 "{}^{}",
487 self.luminous_intensity_unit.to_string(),
488 self.luminous_intensity_count
489 );
490 s_denominator.push(s);
491 } else if self.luminous_intensity_count == -1 {
492 let s = self.luminous_intensity_unit.to_string();
493 s_denominator.push(s.to_string());
494 }
495
496 if self.mass_count <= -2 {
497 let s = format!("{}^{}", self.mass_unit.to_string(), self.mass_count);
498 s_denominator.push(s);
499 } else if self.mass_count == -1 {
500 let s = self.mass_unit.to_string();
501 s_denominator.push(s.to_string());
502 }
503
504 if self.time_count <= -2 {
505 let s = format!(
506 "{}^{}",
507 self.time_unit.to_string(),
508 i32::abs(self.time_count)
509 );
510 s_denominator.push(s);
511 } else if self.time_count == -1 {
512 let s = self.time_unit.to_string();
513 s_denominator.push(s.to_string());
514 }
515
516 if self.temperature_count <= -2 {
517 let s = format!(
518 "{}^{}",
519 self.temperature_unit.to_string(),
520 self.temperature_count
521 );
522 s_denominator.push(s);
523 } else if self.temperature_count == -1 {
524 let s = self.temperature_unit.to_string();
525 s_denominator.push(s.to_string());
526 }
527
528 let mut s_output = String::new();
529 for s in s_numerator.iter() {
530 s_output.push_str(s);
531 s_output.push('·');
532 }
533 if !s_numerator.is_empty() {
534 let mut chars = s_output.chars();
535 chars.next_back();
536 s_output = chars.as_str().to_string();
537 }
538
539 if !s_denominator.is_empty() {
540 s_output.push('/');
541 }
542 for s in s_denominator.iter() {
543 s_output.push_str(s);
544 s_output.push('·');
545 }
546 if !s_denominator.is_empty() {
547 let mut chars = s_output.chars();
548 chars.next_back();
549 s_output = chars.as_str().to_string();
550 }
551 s_output
552 }
553
554 pub fn to_latex(&self) -> String {
555 if !self.has_units() {
556 return format!("${}$", self.value);
557 }
558
559 let mut s_numerator: Vec<String> = Vec::new();
560 let mut s_denominator: Vec<String> = Vec::new();
561
562 if self.mass_count >= 2 {
564 let s = format!("{}^{}", self.mass_unit.to_string(), self.mass_count);
565 s_numerator.push(s);
566 } else if self.mass_count == 1 {
567 let s = self.mass_unit.to_string();
568 s_numerator.push(s.to_string());
569 }
570
571 if self.temperature_count >= 2 {
572 let s = format!(
573 "{}^{}",
574 self.temperature_unit.to_string(),
575 self.temperature_count
576 );
577 s_numerator.push(s);
578 } else if self.temperature_count == 1 {
579 let s = self.temperature_unit.to_latex();
580 s_numerator.push(s.to_string());
581 }
582
583 if self.time_count >= 2 {
584 let s = format!("{}^{}", self.time_unit.to_string(), self.time_count);
585 s_numerator.push(s);
586 } else if self.time_count == 1 {
587 let s = self.time_unit.to_string();
588 s_numerator.push(s.to_string());
589 }
590
591 if self.mass_count <= -2 {
593 let s = format!("{}^{}", self.mass_unit.to_string(), self.mass_count);
594 s_denominator.push(s);
595 } else if self.mass_count == -1 {
596 let s = self.mass_unit.to_string();
597 s_denominator.push(s.to_string());
598 }
599
600 if self.temperature_count <= -2 {
601 let s = format!(
602 "{}^{}",
603 self.temperature_unit.to_string(),
604 self.temperature_count
605 );
606 s_denominator.push(s);
607 } else if self.temperature_count == -1 {
608 let s = self.temperature_unit.to_string();
609 s_denominator.push(s.to_string());
610 }
611
612 if self.time_count <= -2 {
613 let s = format!(
614 "{}^{}",
615 self.time_unit.to_string(),
616 i32::abs(self.time_count)
617 );
618 s_denominator.push(s);
619 } else if self.time_count == -1 {
620 let s = self.time_unit.to_string();
621 s_denominator.push(s.to_string());
622 }
623
624 let mut s_output = format!("${}\\ ", self.value);
625 for s in s_numerator.iter() {
626 s_output.push_str(s);
627 }
628
629 if !s_denominator.is_empty() {
630 s_output.push('/');
631 }
632 for s in s_denominator.iter() {
633 s_output.push_str(s);
634 }
635 s_output.push('$');
636 s_output
637 }
638
639 fn multiply_units(self, other: &EngUnit) -> EngUnit {
640 let mut new_unit = EngUnit::new();
641 new_unit.amount_of_substance_count =
642 self.amount_of_substance_count + other.amount_of_substance_count;
643 new_unit.electric_current_count =
644 self.electric_current_count + other.electric_current_count;
645 new_unit.length_count = self.length_count + other.length_count;
646 new_unit.luminous_intensity_count =
647 self.luminous_intensity_count + other.luminous_intensity_count;
648 new_unit.mass_count = self.mass_count + other.mass_count;
649 new_unit.temperature_count = self.temperature_count + other.temperature_count;
650 new_unit.time_count = self.time_count + other.time_count;
651
652 let mut amount_conversion_factor = AmountOfSubstanceUnit::conversion_factor(
653 &other.amount_of_substance_unit,
654 &self.amount_of_substance_unit,
655 );
656 if other.amount_of_substance_count < 0 {
657 amount_conversion_factor = 1.0 / amount_conversion_factor;
658 }
659
660 let mut electric_conversion_factor = ElectricCurrentUnit::conversion_factor(
661 &other.electric_current_unit,
662 &self.electric_current_unit,
663 );
664 if other.electric_current_count < 0 {
665 electric_conversion_factor = 1.0 / electric_conversion_factor;
666 }
667
668 let mut length_conversion_factor =
669 LengthUnit::conversion_factor(&other.length_unit, &self.length_unit);
670 if other.length_count < 0 {
671 length_conversion_factor = 1.0 / length_conversion_factor;
672 }
673
674 let mut luminous_conversion_factor = LuminousIntensityUnit::conversion_factor(
675 &other.luminous_intensity_unit,
676 &self.luminous_intensity_unit,
677 );
678 if other.luminous_intensity_count < 0 {
679 luminous_conversion_factor = 1.0 / luminous_conversion_factor;
680 }
681
682 let mut mass_conversion_factor =
683 MassUnit::conversion_factor(&other.mass_unit, &self.mass_unit);
684 if other.mass_count < 0 {
685 mass_conversion_factor = 1.0 / mass_conversion_factor;
686 }
687
688 let mut temperature_conversion_factor = TemperatureDeltaUnit::conversion_factor(
689 &other.temperature_unit,
690 &self.temperature_unit,
691 );
692 if other.temperature_count < 0 {
693 temperature_conversion_factor = 1.0 / temperature_conversion_factor;
694 }
695
696 let mut time_conversion_factor =
697 TimeUnit::conversion_factor(&other.time_unit, &self.time_unit);
698 if other.time_count < 0 {
699 time_conversion_factor = 1.0 / time_conversion_factor;
700 }
701
702 new_unit.value = self.value * other.value;
703 new_unit.value *= amount_conversion_factor;
704 new_unit.value *= electric_conversion_factor;
705 new_unit.value *= length_conversion_factor;
706 new_unit.value *= luminous_conversion_factor;
707 new_unit.value *= mass_conversion_factor;
708 new_unit.value *= temperature_conversion_factor;
709 new_unit.value *= time_conversion_factor;
710
711 if new_unit.amount_of_substance_count != 0 {
712 if self.amount_of_substance_count != 0 {
713 new_unit.amount_of_substance_unit = self.amount_of_substance_unit;
714 } else {
715 new_unit.amount_of_substance_unit = other.amount_of_substance_unit.clone();
716 }
717 } else {
718 new_unit.amount_of_substance_unit = AmountOfSubstanceUnit::None;
719 }
720
721 if new_unit.electric_current_count != 0 {
722 if self.electric_current_count != 0 {
723 new_unit.electric_current_unit = self.electric_current_unit;
724 } else {
725 new_unit.electric_current_unit = other.electric_current_unit.clone();
726 }
727 } else {
728 new_unit.electric_current_unit = ElectricCurrentUnit::None;
729 }
730
731 if new_unit.length_count != 0 {
732 if self.length_count != 0 {
733 new_unit.length_unit = self.length_unit;
734 } else {
735 new_unit.length_unit = other.length_unit.clone();
736 }
737 } else {
738 new_unit.length_unit = LengthUnit::None;
739 }
740
741 if new_unit.luminous_intensity_count != 0 {
742 if self.luminous_intensity_count != 0 {
743 new_unit.luminous_intensity_unit = self.luminous_intensity_unit;
744 } else {
745 new_unit.luminous_intensity_unit = other.luminous_intensity_unit.clone();
746 }
747 } else {
748 new_unit.luminous_intensity_unit = LuminousIntensityUnit::None;
749 }
750
751 if new_unit.mass_count != 0 {
752 if self.mass_count != 0 {
753 new_unit.mass_unit = self.mass_unit;
754 } else {
755 new_unit.mass_unit = other.mass_unit.clone();
756 }
757 } else {
758 new_unit.mass_unit = MassUnit::None;
759 }
760
761 if new_unit.temperature_count != 0 {
762 if self.temperature_count != 0 {
763 new_unit.temperature_unit = self.temperature_unit;
764 } else {
765 new_unit.temperature_unit = other.temperature_unit.clone();
766 }
767 } else {
768 new_unit.temperature_unit = TemperatureDeltaUnit::None;
769 }
770
771 if new_unit.time_count != 0 {
772 if self.time_count != 0 {
773 new_unit.time_unit = self.time_unit;
774 } else {
775 new_unit.time_unit = other.time_unit.clone();
776 }
777 } else {
778 new_unit.time_unit = TimeUnit::None;
779 }
780 new_unit
781 }
782
783 fn divide_units(self, other: &EngUnit) -> EngUnit {
784 let recip = other.reciprocal();
785 self.multiply_units(&recip)
786 }
787
788 pub fn reciprocal(&self) -> EngUnit {
789 let mut recip = self.clone();
790 recip.value = 1.0 / recip.value;
791 recip.amount_of_substance_count *= -1;
792 recip.electric_current_count *= -1;
793 recip.length_count *= -1;
794 recip.luminous_intensity_count *= -1;
795 recip.mass_count *= -1;
796 recip.temperature_count *= -1;
797 recip.time_count *= -1;
798 recip
799 }
800
801 pub fn get_complex_unit() {}
802}
803
804impl ops::Mul for EngUnit {
805 type Output = EngUnit;
806 fn mul(self, rhs: Self) -> Self::Output {
807 self.multiply_units(&rhs)
808 }
809}
810
811impl ops::Mul for &EngUnit {
812 type Output = EngUnit;
813 fn mul(self, rhs: Self) -> Self::Output {
814 let new_unit = self.clone();
815 new_unit.multiply_units(rhs)
816 }
817}
818
819impl ops::Div for EngUnit {
820 type Output = EngUnit;
821 fn div(self, rhs: Self) -> Self::Output {
822 self.divide_units(&rhs)
823 }
824}
825
826impl ops::Div for &EngUnit {
827 type Output = EngUnit;
828 fn div(self, rhs: Self) -> Self::Output {
829 let new_unit = self.clone();
830 new_unit.divide_units(rhs)
831 }
832}
833
834impl ops::Mul<f64> for EngUnit {
835 type Output = EngUnit;
836 fn mul(self, rhs: f64) -> Self::Output {
837 let mut new_unit = self.clone();
838 new_unit.value *= rhs;
839 new_unit
840 }
841}
842
843impl ops::Mul<f64> for &EngUnit {
844 type Output = EngUnit;
845 fn mul(self, rhs: f64) -> Self::Output {
846 let mut new_unit = self.clone();
847 new_unit.value *= rhs;
848 new_unit
849 }
850}
851
852impl ops::Mul<EngUnit> for f64 {
853 type Output = EngUnit;
854 fn mul(self, lhs: EngUnit) -> Self::Output {
855 let mut new_unit = lhs.clone();
856 new_unit.value *= self;
857 new_unit
858 }
859}
860
861impl ops::Mul<&EngUnit> for f64 {
862 type Output = EngUnit;
863 fn mul(self, lhs: &EngUnit) -> Self::Output {
864 let mut new_unit = lhs.clone();
865 new_unit.value *= self;
866 new_unit
867 }
868}
869
870pub fn same_units(unit_1: &EngUnit, unit_2: &EngUnit) -> bool {
871 if unit_1.amount_of_substance_unit != unit_2.amount_of_substance_unit {
872 return false;
873 }
874 if unit_1.electric_current_unit != unit_2.electric_current_unit {
875 return false;
876 }
877 if unit_1.length_unit != unit_2.length_unit {
878 return false;
879 }
880 if unit_1.luminous_intensity_unit != unit_2.luminous_intensity_unit {
881 return false;
882 }
883 if unit_1.mass_unit != unit_2.mass_unit {
884 return false;
885 }
886 if unit_1.temperature_unit != unit_2.temperature_unit {
887 return false;
888 }
889 if unit_1.time_unit != unit_2.time_unit {
890 return false;
891 }
892
893 if unit_1.amount_of_substance_count != unit_2.amount_of_substance_count {
894 return false;
895 }
896 if unit_1.electric_current_count != unit_2.electric_current_count {
897 return false;
898 }
899 if unit_1.length_count != unit_2.length_count {
900 return false;
901 }
902 if unit_1.luminous_intensity_count != unit_2.luminous_intensity_count {
903 return false;
904 }
905 if unit_1.mass_count != unit_2.mass_count {
906 return false;
907 }
908 if unit_1.temperature_count != unit_2.temperature_count {
909 return false;
910 }
911 if unit_1.time_count != unit_2.time_count {
912 return false;
913 }
914 true
915}
916
917#[cfg(test)]
918mod tests {
919 use crate::temperature;
920 use crate::*;
921
922 #[test]
923 fn new_eng_unt() {
924 let new_unit = EngUnit::new();
925 assert_eq!(0, new_unit.length_count);
926 assert_eq!(0, new_unit.time_count);
927 assert_eq!(0, new_unit.mass_count);
928 assert_eq!(0, new_unit.temperature_count);
929 assert_eq!(0, new_unit.electric_current_count);
930 assert_eq!(0, new_unit.luminous_intensity_count);
931 assert_eq!(0, new_unit.amount_of_substance_count);
932 assert_eq!(false, new_unit.has_units());
933 }
934
935 #[test]
936 fn multiply_numerator_check() {
937 let unit_1 = EngUnit::new();
938 let mut unit_2 = EngUnit::new();
939 unit_2.length_count = 1;
940 unit_2.mass_count = 1;
941 unit_2.time_count = 1;
942 unit_2.temperature_count = 1;
943 unit_2.electric_current_count = 1;
944 unit_2.luminous_intensity_count = 1;
945 unit_2.amount_of_substance_count = 1;
946
947 let unit3 = unit_1.multiply_units(&unit_2);
948 assert_eq!(1, unit3.length_count);
949 assert_eq!(1, unit3.mass_count);
950 assert_eq!(1, unit3.time_count);
951 assert_eq!(1, unit3.temperature_count);
952 assert_eq!(1, unit3.electric_current_count);
953 assert_eq!(1, unit3.luminous_intensity_count);
954 assert_eq!(1, unit3.amount_of_substance_count);
955 assert_eq!(true, unit3.has_units());
956 }
957
958 #[test]
959 fn multiply_operator_numerator_check() {
960 let unit_1 = EngUnit::new();
961 let mut unit_2 = EngUnit::new();
962 unit_2.length_count = 1;
963 unit_2.mass_count = 1;
964 unit_2.time_count = 1;
965 unit_2.temperature_count = 1;
966 unit_2.electric_current_count = 1;
967 unit_2.luminous_intensity_count = 1;
968 unit_2.amount_of_substance_count = 1;
969
970 let unit3 = unit_1 * unit_2;
971 assert_eq!(1, unit3.length_count);
972 assert_eq!(1, unit3.mass_count);
973 assert_eq!(1, unit3.time_count);
974 assert_eq!(1, unit3.temperature_count);
975 assert_eq!(1, unit3.electric_current_count);
976 assert_eq!(1, unit3.luminous_intensity_count);
977 assert_eq!(1, unit3.amount_of_substance_count);
978 assert_eq!(true, unit3.has_units());
979 }
980
981 #[test]
982 fn multiply_denominator_check() {
983 let unit_1 = EngUnit::new();
984 let mut unit_2 = EngUnit::new();
985 unit_2.length_count = -1;
986 unit_2.mass_count = -1;
987 unit_2.time_count = -1;
988 unit_2.temperature_count = -1;
989 unit_2.electric_current_count = -1;
990 unit_2.luminous_intensity_count = -1;
991 unit_2.amount_of_substance_count = -1;
992
993 let unit3 = unit_1.multiply_units(&unit_2);
994 assert_eq!(-1, unit3.length_count);
995 assert_eq!(-1, unit3.mass_count);
996 assert_eq!(-1, unit3.time_count);
997 assert_eq!(-1, unit3.temperature_count);
998 assert_eq!(-1, unit3.electric_current_count);
999 assert_eq!(-1, unit3.luminous_intensity_count);
1000 assert_eq!(-1, unit3.amount_of_substance_count);
1001 assert_eq!(true, unit3.has_units());
1002 }
1003
1004 #[test]
1005 fn multiply_operator_denominator_check() {
1006 let unit_1 = EngUnit::new();
1007 let mut unit_2 = EngUnit::new();
1008 unit_2.length_count = -1;
1009 unit_2.mass_count = -1;
1010 unit_2.time_count = -1;
1011 unit_2.temperature_count = -1;
1012 unit_2.electric_current_count = -1;
1013 unit_2.luminous_intensity_count = -1;
1014 unit_2.amount_of_substance_count = -1;
1015
1016 let unit3 = unit_1 * unit_2;
1017 assert_eq!(-1, unit3.length_count);
1018 assert_eq!(-1, unit3.mass_count);
1019 assert_eq!(-1, unit3.time_count);
1020 assert_eq!(-1, unit3.temperature_count);
1021 assert_eq!(-1, unit3.electric_current_count);
1022 assert_eq!(-1, unit3.luminous_intensity_count);
1023 assert_eq!(-1, unit3.amount_of_substance_count);
1024 assert_eq!(true, unit3.has_units());
1025 }
1026
1027 #[test]
1028 fn multiply_cancel_out_check() {
1029 let mut unit_1 = EngUnit::new();
1030 unit_1.length_count = -1;
1031 unit_1.mass_count = -1;
1032 unit_1.time_count = -1;
1033 unit_1.temperature_count = -1;
1034 unit_1.electric_current_count = -1;
1035 unit_1.luminous_intensity_count = -1;
1036 unit_1.amount_of_substance_count = -1;
1037 let mut unit_2 = EngUnit::new();
1038 unit_2.length_count = 1;
1039 unit_2.mass_count = 1;
1040 unit_2.time_count = 1;
1041 unit_2.temperature_count = 1;
1042 unit_2.electric_current_count = 1;
1043 unit_2.luminous_intensity_count = 1;
1044 unit_2.amount_of_substance_count = 1;
1045
1046 let unit3 = unit_1.multiply_units(&unit_2);
1047 assert_eq!(0, unit3.length_count);
1048 assert_eq!(0, unit3.mass_count);
1049 assert_eq!(0, unit3.time_count);
1050 assert_eq!(0, unit3.temperature_count);
1051 assert_eq!(0, unit3.electric_current_count);
1052 assert_eq!(0, unit3.luminous_intensity_count);
1053 assert_eq!(0, unit3.amount_of_substance_count);
1054 }
1055
1056 #[test]
1057 fn multiply_operator_cancel_out_check() {
1058 let mut unit_1 = EngUnit::new();
1059 unit_1.length_count = -1;
1060 unit_1.mass_count = -1;
1061 unit_1.time_count = -1;
1062 unit_1.temperature_count = -1;
1063 unit_1.electric_current_count = -1;
1064 unit_1.luminous_intensity_count = -1;
1065 unit_1.amount_of_substance_count = -1;
1066 let mut unit_2 = EngUnit::new();
1067 unit_2.length_count = 1;
1068 unit_2.mass_count = 1;
1069 unit_2.time_count = 1;
1070 unit_2.temperature_count = 1;
1071 unit_2.electric_current_count = 1;
1072 unit_2.luminous_intensity_count = 1;
1073 unit_2.amount_of_substance_count = 1;
1074
1075 let unit3 = unit_1 * unit_2;
1076 assert_eq!(0, unit3.length_count);
1077 assert_eq!(0, unit3.mass_count);
1078 assert_eq!(0, unit3.time_count);
1079 assert_eq!(0, unit3.temperature_count);
1080 assert_eq!(0, unit3.electric_current_count);
1081 assert_eq!(0, unit3.luminous_intensity_count);
1082 assert_eq!(0, unit3.amount_of_substance_count);
1083 }
1084
1085 #[test]
1086 fn temperature_unit_new() {
1087 let mut unit_1 = EngUnit::new();
1088 unit_1.value = 100.0;
1089 unit_1.temperature_count = 1;
1090 unit_1.temperature_unit = TemperatureDeltaUnit::C;
1091 let unit_2 = EngUnit::new();
1092 let unit_3 = unit_1 * unit_2;
1093 assert_eq!(100.0, unit_3.value);
1094 assert_eq!(1, unit_3.temperature_count);
1095 assert_eq!(TemperatureDeltaUnit::C, unit_3.temperature_unit);
1096 assert_eq!(true, unit_3.has_units())
1097 }
1098
1099 #[test]
1100 fn temperature_c_div_c() {
1101 let unit_1 = temperature!(1.0, TemperatureDeltaUnit::C);
1102 let unit_2 = temperature!(2.0, TemperatureDeltaUnit::C);
1103 let unit_3 = unit_1 / unit_2;
1104 assert_eq!(0.5, unit_3.value);
1105 assert_eq!("0.50", unit_3.to_string());
1106 assert_eq!(0, unit_3.temperature_count);
1107 assert_eq!(TemperatureDeltaUnit::None, unit_3.temperature_unit);
1108 assert!(!unit_3.has_units())
1109 }
1110
1111 #[test]
1112 fn temperature_k_div_r() {
1113 let unit_1 = temperature!(1.0, TemperatureDeltaUnit::K);
1114 let unit_2 = temperature!(1.0, TemperatureDeltaUnit::R);
1115 let unit_3 = unit_1 / unit_2;
1116 let expected = 9.0 / 5.0;
1117 assert!(f64::abs(expected - unit_3.value) < 0.000001);
1118 assert_eq!("1.80", unit_3.to_string());
1119 assert_eq!(TemperatureDeltaUnit::None, unit_3.temperature_unit);
1120 assert!(!unit_3.has_units())
1121 }
1122}