1use crate::{Quantity, Unit};
24use qtty_derive::Unit;
25
26pub use crate::dimension::Force;
28
29pub trait ForceUnit: Unit<Dim = Force> {}
31impl<T: Unit<Dim = Force>> ForceUnit for T {}
32
33#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
39#[unit(symbol = "N", dimension = Force, ratio = 1.0)]
40pub struct Newton;
41pub type N = Newton;
43pub type Newtons = Quantity<N>;
45pub const NEWTON: Newtons = Newtons::new(1.0);
47
48macro_rules! si_newton {
49 ($name:ident, $sym:literal, $ratio:expr, $alias:ident, $qty:ident, $one:ident) => {
50 #[doc = concat!("SI-prefixed newton unit (", stringify!($ratio), " N).")]
51 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
52 #[unit(symbol = $sym, dimension = Force, ratio = $ratio)]
53 pub struct $name;
54 #[doc = concat!("Type alias shorthand for [`", stringify!($name), "`].")]
55 pub type $alias = $name;
56 #[doc = concat!("A quantity measured in ", stringify!($name), "s.")]
57 pub type $qty = Quantity<$alias>;
58 #[doc = concat!("One ", stringify!($name), ".")]
59 pub const $one: $qty = $qty::new(1.0);
60 };
61}
62
63si_newton!(Micronewton, "µN", 1e-6, Un, Micronewtons, MICRONEWTON);
64si_newton!(Millinewton, "mN", 1e-3, Mn, Millinewtons, MILLINEWTON);
65si_newton!(Kilonewton, "kN", 1e3, Kn, Kilonewtons, KILONEWTON);
66si_newton!(Meganewton, "MN", 1e6, MN, Meganewtons, MEGANEWTON);
67si_newton!(Giganewton, "GN", 1e9, GN, Giganewtons, GIGANEWTON);
68
69#[cfg(feature = "fundamental-physics")]
75#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
76#[unit(symbol = "dyn", dimension = Force, ratio = 1e-5)]
77pub struct Dyne;
78#[cfg(feature = "fundamental-physics")]
80pub type Dynes = Quantity<Dyne>;
81
82#[cfg(feature = "customary")]
87#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
88#[unit(symbol = "lbf", dimension = Force, ratio = 4.448_221_615_260_5)]
89pub struct PoundForce;
90#[cfg(feature = "customary")]
92pub type PoundsForce = Quantity<PoundForce>;
93
94#[macro_export]
100#[doc(hidden)]
101macro_rules! force_units {
102 ($cb:path) => {
103 $cb!(
104 Newton,
105 Micronewton,
106 Millinewton,
107 Kilonewton,
108 Meganewton,
109 Giganewton
110 );
111 };
112}
113
114force_units!(crate::impl_unit_from_conversions);
116
117#[cfg(feature = "cross-unit-ops")]
118force_units!(crate::impl_unit_cross_unit_ops);
119
120#[cfg(all(feature = "customary", feature = "fundamental-physics"))]
122crate::__impl_from_each_extra_to_bases!(
123 {PoundForce}
124 Dyne
125);
126#[cfg(all(
127 feature = "customary",
128 feature = "fundamental-physics",
129 feature = "cross-unit-ops"
130))]
131crate::__impl_cross_ops_each_extra_to_bases!(
132 {PoundForce}
133 Dyne
134);
135
136#[cfg(test)]
138force_units!(crate::assert_units_are_builtin);
139
140#[cfg(feature = "fundamental-physics")]
142#[macro_export]
143#[doc(hidden)]
144macro_rules! force_fundamental_physics_units {
145 ($cb:path) => {
146 $cb!(Dyne);
147 };
148}
149
150#[cfg(feature = "customary")]
152#[macro_export]
153#[doc(hidden)]
154macro_rules! force_customary_units {
155 ($cb:path) => {
156 $cb!(PoundForce);
157 };
158}
159
160#[cfg(all(test, feature = "std"))]
161mod tests {
162 use super::*;
163 use approx::assert_abs_diff_eq;
164
165 #[test]
166 fn kilonewton_to_newton() {
167 let kn = Kilonewtons::new(1.0);
168 let n: Newtons = kn.to();
169 assert_abs_diff_eq!(n.value(), 1_000.0, epsilon = 1e-12);
170 }
171
172 #[test]
173 fn newton_to_millinewton() {
174 let n = Newtons::new(1.0);
175 let mn: Millinewtons = n.to();
176 assert_abs_diff_eq!(mn.value(), 1_000.0, epsilon = 1e-12);
177 }
178
179 #[test]
180 #[cfg(feature = "fundamental-physics")]
181 fn newton_to_dyne() {
182 let n = Newtons::new(1.0);
183 let d: Dynes = n.to();
184 assert_abs_diff_eq!(d.value(), 1e5, epsilon = 1e-7);
185 }
186
187 #[test]
188 #[cfg(feature = "customary")]
189 fn newton_to_lbf() {
190 let n = Newtons::new(4.448_221_615_260_5);
191 let lbf: PoundsForce = n.to();
192 assert_abs_diff_eq!(lbf.value(), 1.0, epsilon = 1e-9);
193 }
194}