qtty_core/units/
unitless.rs1use crate::dimension::{
18 Acceleration, AmountOfSubstance, Angular, Area, Current, Energy, Force, FrequencyDim, Length,
19 LuminousIntensity, Mass, Power, Temperature, Time, VelocityDim, Volume,
20};
21use crate::scalar::Scalar;
22use crate::{Quantity, Unit, Unitless};
23
24trait SupportedDimension {}
25impl SupportedDimension for Length {}
26impl SupportedDimension for Time {}
27impl SupportedDimension for Mass {}
28impl SupportedDimension for Temperature {}
29impl SupportedDimension for Current {}
30impl SupportedDimension for AmountOfSubstance {}
31impl SupportedDimension for LuminousIntensity {}
32impl SupportedDimension for Angular {}
33impl SupportedDimension for Area {}
34impl SupportedDimension for Volume {}
35impl SupportedDimension for VelocityDim {}
36impl SupportedDimension for Acceleration {}
37impl SupportedDimension for Force {}
38impl SupportedDimension for Energy {}
39impl SupportedDimension for Power {}
40impl SupportedDimension for FrequencyDim {}
41
42trait DimensionedUnit: Unit {}
43impl<U: Unit> DimensionedUnit for U where U::Dim: SupportedDimension {}
44
45impl<U: DimensionedUnit, S: Scalar> From<Quantity<U, S>> for Quantity<Unitless, S> {
46 #[inline]
47 fn from(quantity: Quantity<U, S>) -> Self {
48 Self::new(quantity.value())
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::units::angular::Degrees;
56 use crate::units::length::Meters;
57 use crate::units::mass::Kilogram;
58 use crate::units::mass::Kilograms;
59 use crate::units::time::Seconds;
60 use crate::Unit;
61 use approx::assert_abs_diff_eq;
62 use proptest::prelude::*;
63
64 #[test]
69 fn unitless_new_and_value() {
70 let u: Quantity<Unitless> = Quantity::new(42.0);
71 assert_eq!(u.value(), 42.0);
72 }
73
74 #[test]
75 fn unitless_from_f64() {
76 let u: Quantity<Unitless> = 1.23456.into();
77 assert_abs_diff_eq!(u.value(), 1.23456, epsilon = 1e-12);
78 }
79
80 #[test]
85 fn display_unitless() {
86 let u: Quantity<Unitless> = Quantity::new(123.456);
87 let s = format!("{}", u);
88 assert_eq!(s, "123.456");
89 }
90
91 #[test]
92 fn display_unitless_integer() {
93 let u: Quantity<Unitless> = Quantity::new(42.0);
94 let s = format!("{}", u);
95 assert_eq!(s, "42");
96 }
97
98 #[test]
103 fn from_length() {
104 let m = Meters::new(42.0);
105 let u: Quantity<Unitless> = m.into();
106 assert_eq!(u.value(), 42.0);
107 }
108
109 #[test]
110 fn from_time() {
111 let t = Seconds::new(5.0);
112 let u: Quantity<Unitless> = t.into();
113 assert_eq!(u.value(), 5.0);
114 }
115
116 #[test]
117 fn from_mass() {
118 let m = Kilograms::new(2.5);
119 let u: Quantity<Unitless> = m.into();
120 assert_eq!(u.value(), 2.5);
121 }
122
123 #[test]
124 fn from_angular() {
125 let a = Degrees::new(90.0);
126 let u: Quantity<Unitless> = a.into();
127 assert_eq!(u.value(), 90.0);
128 }
129
130 #[test]
131 fn from_mass_preserves_non_default_scalar_type() {
132 let m: Quantity<Kilogram, i32> = Quantity::new(7);
133 let u: Quantity<Unitless, i32> = m.into();
134 assert_eq!(u.value(), 7);
135 }
136
137 #[test]
142 fn unitless_addition() {
143 let a: Quantity<Unitless> = Quantity::new(3.0);
144 let b: Quantity<Unitless> = Quantity::new(4.0);
145 assert_eq!((a + b).value(), 7.0);
146 }
147
148 #[test]
149 fn unitless_subtraction() {
150 let a: Quantity<Unitless> = Quantity::new(10.0);
151 let b: Quantity<Unitless> = Quantity::new(3.0);
152 assert_eq!((a - b).value(), 7.0);
153 }
154
155 #[test]
156 fn unitless_multiplication() {
157 let a: Quantity<Unitless> = Quantity::new(3.0);
158 assert_eq!((a * 4.0).value(), 12.0);
159 }
160
161 #[test]
162 fn unitless_division() {
163 let a: Quantity<Unitless> = Quantity::new(12.0);
164 assert_eq!((a / 4.0).value(), 3.0);
165 }
166
167 #[test]
172 fn unitless_ratio() {
173 assert_eq!(Unitless::RATIO, 1.0);
174 }
175
176 #[test]
177 fn unitless_symbol() {
178 assert_eq!(Unitless::SYMBOL, "");
179 }
180
181 proptest! {
186 #[test]
187 fn prop_unitless_arithmetic(a in -1e6..1e6f64, b in -1e6..1e6f64) {
188 let qa: Quantity<Unitless> = Quantity::new(a);
189 let qb: Quantity<Unitless> = Quantity::new(b);
190
191 prop_assert!((((qa + qb).value() - (qb + qa).value()).abs() < 1e-9));
193
194 prop_assert!(((qa + qb).value() - (a + b)).abs() < 1e-9);
196 }
197
198 #[test]
199 fn prop_from_length_preserves_value(v in -1e6..1e6f64) {
200 let m = Meters::new(v);
201 let u: Quantity<Unitless> = m.into();
202 prop_assert!((u.value() - v).abs() < 1e-12);
203 }
204
205 #[test]
206 fn prop_from_time_preserves_value(v in -1e6..1e6f64) {
207 let t = Seconds::new(v);
208 let u: Quantity<Unitless> = t.into();
209 prop_assert!((u.value() - v).abs() < 1e-12);
210 }
211 }
212}