1use crate::{Quantity, Unit};
38use core::f64::consts::PI;
39use qtty_derive::Unit;
40
41pub use crate::dimension::Length;
43
44pub trait LengthUnit: Unit<Dim = Length> {}
46impl<T: Unit<Dim = Length>> LengthUnit for T {}
47
48#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
54#[unit(symbol = "m", dimension = Length, ratio = 1.0)]
55pub struct Meter;
56pub type Meters = Quantity<Meter>;
58pub const M: Meters = Meters::new(1.0);
60
61#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
63#[unit(symbol = "km", dimension = Length, ratio = 1_000.0)]
64pub struct Kilometer;
65pub type Km = Kilometer;
67pub type Kilometers = Quantity<Km>;
69pub const KM: Kilometers = Kilometers::new(1.0);
71
72#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
74#[unit(symbol = "cm", dimension = Length, ratio = 1e-2)]
75pub struct Centimeter;
76pub type Cm = Centimeter;
78pub type Centimeters = Quantity<Cm>;
80pub const CM: Centimeters = Centimeters::new(1.0);
82
83#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
85#[unit(symbol = "mm", dimension = Length, ratio = 1e-3)]
86pub struct Millimeter;
87pub type Mm = Millimeter;
89pub type Millimeters = Quantity<Mm>;
91pub const MM: Millimeters = Millimeters::new(1.0);
93
94#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
96#[unit(symbol = "μm", dimension = Length, ratio = 1e-6)]
97pub struct Micrometer;
98pub type Um = Micrometer;
100pub type Micrometers = Quantity<Um>;
102pub const UM: Micrometers = Micrometers::new(1.0);
104
105#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
107#[unit(symbol = "nm", dimension = Length, ratio = 1e-9)]
108pub struct Nanometer;
109pub type Nm = Nanometer;
111pub type Nanometers = Quantity<Nm>;
113pub const NM: Nanometers = Nanometers::new(1.0);
115
116#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
118#[unit(symbol = "pm", dimension = Length, ratio = 1e-12)]
119pub struct Picometer;
120pub type Picometers = Quantity<Picometer>;
122pub const PMETER: Picometers = Picometers::new(1.0);
124
125#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
127#[unit(symbol = "fm", dimension = Length, ratio = 1e-15)]
128pub struct Femtometer;
129pub type Femtometers = Quantity<Femtometer>;
131pub const FM: Femtometers = Femtometers::new(1.0);
133
134#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
136#[unit(symbol = "am", dimension = Length, ratio = 1e-18)]
137pub struct Attometer;
138pub type Attometers = Quantity<Attometer>;
140pub const AM: Attometers = Attometers::new(1.0);
142
143#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
145#[unit(symbol = "zm", dimension = Length, ratio = 1e-21)]
146pub struct Zeptometer;
147pub type Zeptometers = Quantity<Zeptometer>;
149pub const ZMETER: Zeptometers = Zeptometers::new(1.0);
151
152#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
154#[unit(symbol = "ym", dimension = Length, ratio = 1e-24)]
155pub struct Yoctometer;
156pub type Yoctometers = Quantity<Yoctometer>;
158pub const YMETER: Yoctometers = Yoctometers::new(1.0);
160
161#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
163#[unit(symbol = "Mm", dimension = Length, ratio = 1e6)]
164pub struct Megameter;
165pub type MegaMeter = Megameter;
167pub type Megameters = Quantity<Megameter>;
169pub const MEGAMETER: Megameters = Megameters::new(1.0);
171
172#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
174#[unit(symbol = "dm", dimension = Length, ratio = 1e-1)]
175pub struct Decimeter;
176pub type Decimeters = Quantity<Decimeter>;
178pub const DM: Decimeters = Decimeters::new(1.0);
180
181#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
183#[unit(symbol = "dam", dimension = Length, ratio = 1e1)]
184pub struct Decameter;
185pub type Decameters = Quantity<Decameter>;
187pub const DAM: Decameters = Decameters::new(1.0);
189
190#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
192#[unit(symbol = "hm", dimension = Length, ratio = 1e2)]
193pub struct Hectometer;
194pub type Hectometers = Quantity<Hectometer>;
196pub const HM: Hectometers = Hectometers::new(1.0);
198
199#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
201#[unit(symbol = "Gm", dimension = Length, ratio = 1e9)]
202pub struct Gigameter;
203pub type Gigameters = Quantity<Gigameter>;
205pub const GM: Gigameters = Gigameters::new(1.0);
207
208#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
210#[unit(symbol = "Tm", dimension = Length, ratio = 1e12)]
211pub struct Terameter;
212pub type Terameters = Quantity<Terameter>;
214pub const TM: Terameters = Terameters::new(1.0);
216
217#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
219#[unit(symbol = "Pm", dimension = Length, ratio = 1e15)]
220pub struct Petameter;
221pub type Petameters = Quantity<Petameter>;
223pub const PM: Petameters = Petameters::new(1.0);
225
226#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
228#[unit(symbol = "Em", dimension = Length, ratio = 1e18)]
229pub struct Exameter;
230pub type Exameters = Quantity<Exameter>;
232pub const EM: Exameters = Exameters::new(1.0);
234
235#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
237#[unit(symbol = "Zm", dimension = Length, ratio = 1e21)]
238pub struct Zettameter;
239pub type Zettameters = Quantity<Zettameter>;
241pub const ZM: Zettameters = Zettameters::new(1.0);
243
244#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
246#[unit(symbol = "Ym", dimension = Length, ratio = 1e24)]
247pub struct Yottameter;
248pub type Yottameters = Quantity<Yottameter>;
250pub const YM: Yottameters = Yottameters::new(1.0);
252
253#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
259#[unit(symbol = "au", dimension = Length, ratio = 149_597_870_700.0)]
260pub struct AstronomicalUnit;
261pub type Au = AstronomicalUnit;
263pub type AstronomicalUnits = Quantity<Au>;
265pub const AU: AstronomicalUnits = AstronomicalUnits::new(1.0);
267
268const SPEED_OF_LIGHT_M_PER_S: f64 = 299_792_458.0;
270const SECONDS_PER_DAY: f64 = 86_400.0;
271const DAYS_PER_JULIAN_YEAR: f64 = 36525.0 / 100.0; const SECONDS_PER_JULIAN_YEAR: f64 = SECONDS_PER_DAY * DAYS_PER_JULIAN_YEAR;
273const METERS_PER_LIGHT_YEAR: f64 = SPEED_OF_LIGHT_M_PER_S * SECONDS_PER_JULIAN_YEAR;
274
275#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
277#[unit(symbol = "ly", dimension = Length, ratio = METERS_PER_LIGHT_YEAR)]
278pub struct LightYear;
279pub type Ly = LightYear;
281pub type LightYears = Quantity<Ly>;
283pub const LY: LightYears = LightYears::new(1.0);
285
286#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
288#[unit(symbol = "pc", dimension = Length, ratio = 149_597_870_700.0 * (648_000.0 / PI))]
289pub struct Parsec;
290pub type Pc = Parsec;
292pub type Parsecs = Quantity<Pc>;
294pub const PC: Parsecs = Parsecs::new(1.0);
296
297#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
299#[unit(symbol = "kpc", dimension = Length, ratio = 1_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
300pub struct Kiloparsec;
301pub type Kiloparsecs = Quantity<Kiloparsec>;
303pub const KPC: Kiloparsecs = Kiloparsecs::new(1.0);
305
306#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
308#[unit(symbol = "Mpc", dimension = Length, ratio = 1_000_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
309pub struct Megaparsec;
310pub type Megaparsecs = Quantity<Megaparsec>;
312pub const MPC: Megaparsecs = Megaparsecs::new(1.0);
314
315#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
317#[unit(symbol = "Gpc", dimension = Length, ratio = 1_000_000_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
318pub struct Gigaparsec;
319pub type Gigaparsecs = Quantity<Gigaparsec>;
321pub const GPC: Gigaparsecs = Gigaparsecs::new(1.0);
323
324#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
330#[unit(symbol = "in", dimension = Length, ratio = 254.0 / 10_000.0)]
331pub struct Inch;
332pub type Inches = Quantity<Inch>;
334pub const INCH: Inches = Inches::new(1.0);
336
337#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
339#[unit(symbol = "ft", dimension = Length, ratio = 3048.0 / 10_000.0)]
340pub struct Foot;
341pub type Feet = Quantity<Foot>;
343pub const FT: Feet = Feet::new(1.0);
345
346#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
348#[unit(symbol = "yd", dimension = Length, ratio = 9144.0 / 10_000.0)]
349pub struct Yard;
350pub type Yards = Quantity<Yard>;
352pub const YD: Yards = Yards::new(1.0);
354
355#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
357#[unit(symbol = "mi", dimension = Length, ratio = 1_609_344.0 / 1_000.0)]
358pub struct Mile;
359pub type Miles = Quantity<Mile>;
361pub const MI: Miles = Miles::new(1.0);
363
364#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
366#[unit(symbol = "nmi", dimension = Length, ratio = 1_852.0)]
367pub struct NauticalMile;
368pub type NauticalMiles = Quantity<NauticalMile>;
370pub const NMI: NauticalMiles = NauticalMiles::new(1.0);
372
373#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
375#[unit(symbol = "ch", dimension = Length, ratio = 66.0 * (3048.0 / 10_000.0))]
376pub struct Chain;
377pub type Chains = Quantity<Chain>;
379pub const CHAIN: Chains = Chains::new(1.0);
381
382#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
384#[unit(symbol = "rd", dimension = Length, ratio = 16.5 * (3048.0 / 10_000.0))]
385pub struct Rod;
386pub type Rods = Quantity<Rod>;
388pub const ROD: Rods = Rods::new(1.0);
390
391#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
393#[unit(symbol = "lk", dimension = Length, ratio = (66.0 / 100.0) * (3048.0 / 10_000.0))]
394pub struct Link;
395pub type Links = Quantity<Link>;
397pub const LINK: Links = Links::new(1.0);
399
400#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
402#[unit(symbol = "ftm", dimension = Length, ratio = 6.0 * (3048.0 / 10_000.0))]
403pub struct Fathom;
404pub type Fathoms = Quantity<Fathom>;
406pub const FTM: Fathoms = Fathoms::new(1.0);
408
409#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
415#[unit(symbol = "Cmer", dimension = Length, ratio = 40_007_863.0)]
416pub struct EarthMeridionalCircumference;
417pub type EarthMeridionalCircumferences = Quantity<EarthMeridionalCircumference>;
419pub const C_MERIDIONAL: EarthMeridionalCircumferences = EarthMeridionalCircumferences::new(1.0);
421
422#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
424#[unit(symbol = "Ceq", dimension = Length, ratio = 40_075_017.0)]
425pub struct EarthEquatorialCircumference;
426pub type EarthEquatorialCircumferences = Quantity<EarthEquatorialCircumference>;
428pub const C_EQUATORIAL: EarthEquatorialCircumferences = EarthEquatorialCircumferences::new(1.0);
430
431#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
437#[unit(symbol = "a0", dimension = Length, ratio = 5.291_772_109_03e-11)]
438pub struct BohrRadius;
439pub type BohrRadii = Quantity<BohrRadius>;
441pub const A0: BohrRadii = BohrRadii::new(1.0);
443
444#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
446#[unit(symbol = "re", dimension = Length, ratio = 2.817_940_326_2e-15)]
447pub struct ClassicalElectronRadius;
448pub type ClassicalElectronRadii = Quantity<ClassicalElectronRadius>;
450pub const RE: ClassicalElectronRadii = ClassicalElectronRadii::new(1.0);
452
453#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
455#[unit(symbol = "lp", dimension = Length, ratio = 1.616_255e-35)]
456pub struct PlanckLength;
457pub type PlanckLengths = Quantity<PlanckLength>;
459pub const LP: PlanckLengths = PlanckLengths::new(1.0);
461
462#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
464#[unit(symbol = "lambda_bar_e", dimension = Length, ratio = 3.861_592_679_6e-13)]
465pub struct ElectronReducedComptonWavelength;
466pub type ElectronReducedComptonWavelengths = Quantity<ElectronReducedComptonWavelength>;
468pub const LAMBDA_BAR_E: ElectronReducedComptonWavelengths =
470 ElectronReducedComptonWavelengths::new(1.0);
471
472pub mod nominal {
481 use super::*;
482
483 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
485 #[unit(symbol = "Rsun", dimension = Length, ratio = 695_700_000.0)]
486 pub struct SolarRadius;
487 pub type SolarRadiuses = Quantity<SolarRadius>;
489 pub const RSUN: SolarRadiuses = SolarRadiuses::new(1.0);
491
492 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
494 #[unit(symbol = "Rearth", dimension = Length, ratio = 6_371_000.0)]
495 pub struct EarthRadius;
496 pub type EarthRadii = Quantity<EarthRadius>;
498 pub const R_EARTH: EarthRadii = EarthRadii::new(1.0);
500
501 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
503 #[unit(symbol = "Rearth_eq", dimension = Length, ratio = 6_378_137.0)]
504 pub struct EarthEquatorialRadius;
505 pub type EarthEquatorialRadii = Quantity<EarthEquatorialRadius>;
507 pub const R_EARTH_EQ: EarthEquatorialRadii = EarthEquatorialRadii::new(1.0);
509
510 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
512 #[unit(symbol = "Rearth_p", dimension = Length, ratio = 6_356_752.314_2)]
513 pub struct EarthPolarRadius;
514 pub type EarthPolarRadii = Quantity<EarthPolarRadius>;
516 pub const R_EARTH_P: EarthPolarRadii = EarthPolarRadii::new(1.0);
518
519 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
521 #[unit(symbol = "Rmoon", dimension = Length, ratio = 1_737_400.0)]
522 pub struct LunarRadius;
523 pub type LunarRadii = Quantity<LunarRadius>;
525 pub const R_MOON: LunarRadii = LunarRadii::new(1.0);
527
528 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
530 #[unit(symbol = "Rjup", dimension = Length, ratio = 71_492_000.0)]
531 pub struct JupiterRadius;
532 pub type JupiterRadii = Quantity<JupiterRadius>;
534 pub const R_JUPITER: JupiterRadii = JupiterRadii::new(1.0);
536
537 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
539 #[unit(symbol = "LD", dimension = Length, ratio = 384_400_000.0)]
540 pub struct LunarDistance;
541 pub type LunarDistances = Quantity<LunarDistance>;
543 pub const LD: LunarDistances = LunarDistances::new(1.0);
545
546 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
548 #[unit(symbol = "Dsun", dimension = Length, ratio = 2.0 * 695_700_000.0)]
549 pub struct SolarDiameter;
550 pub type SolarDiameters = Quantity<SolarDiameter>;
552 pub const D_SUN: SolarDiameters = SolarDiameters::new(1.0);
554
555 crate::impl_unit_conversions!(SolarRadius, Kilometer);
559}
560
561crate::impl_unit_conversions!(
567 Meter,
568 Decimeter,
569 Centimeter,
570 Millimeter,
571 Micrometer,
572 Nanometer,
573 Picometer,
574 Femtometer,
575 Attometer,
576 Zeptometer,
577 Yoctometer,
578 Decameter,
579 Hectometer,
580 Kilometer,
581 Megameter,
582 Gigameter,
583 Terameter,
584 Petameter,
585 Exameter,
586 Zettameter,
587 Yottameter,
588 AstronomicalUnit,
589 LightYear,
590 Parsec,
591 Kiloparsec,
592 Megaparsec,
593 Gigaparsec,
594 Inch,
595 Foot,
596 Yard,
597 Mile,
598 NauticalMile,
599 Chain,
600 Rod,
601 Link,
602 Fathom,
603 EarthMeridionalCircumference,
604 EarthEquatorialCircumference,
605 BohrRadius,
606 ClassicalElectronRadius,
607 PlanckLength,
608 ElectronReducedComptonWavelength
609);
610
611#[cfg(test)]
612mod tests {
613 use super::nominal::SolarRadiuses;
614 use super::*;
615 use approx::{assert_abs_diff_eq, assert_relative_eq};
616 use proptest::prelude::*;
617
618 #[test]
623 fn kilometer_to_meter() {
624 let km = Kilometers::new(1.0);
625 let m = km.to::<Meter>();
626 assert_abs_diff_eq!(m.value(), 1000.0, epsilon = 1e-9);
627 }
628
629 #[test]
630 fn meter_to_kilometer() {
631 let m = Meters::new(1000.0);
632 let km = m.to::<Kilometer>();
633 assert_abs_diff_eq!(km.value(), 1.0, epsilon = 1e-12);
634 }
635
636 #[test]
637 fn au_to_meters() {
638 let au = AstronomicalUnits::new(1.0);
639 let m = au.to::<Meter>();
640 assert_abs_diff_eq!(m.value(), 149_597_870_700.0, epsilon = 1e-6);
642 }
643
644 #[test]
645 fn au_to_kilometers() {
646 let au = AstronomicalUnits::new(1.0);
647 let km = au.to::<Kilometer>();
648 assert_relative_eq!(km.value(), 149_597_870.7, max_relative = 1e-12);
650 }
651
652 #[test]
653 fn light_year_to_meters() {
654 let ly = LightYears::new(1.0);
655 let m = ly.to::<Meter>();
656 assert_relative_eq!(m.value(), METERS_PER_LIGHT_YEAR, max_relative = 1e-12);
658 }
659
660 #[test]
661 fn light_year_to_kilometers() {
662 let ly = LightYears::new(1.0);
663 let km = ly.to::<Kilometer>();
664 assert_relative_eq!(km.value(), 9_460_730_472_580.000_8, max_relative = 1e-9);
666 }
667
668 #[test]
673 fn au_to_light_year() {
674 let au = AstronomicalUnits::new(1.0);
675 let ly = au.to::<LightYear>();
676 assert_relative_eq!(ly.value(), 1.582e-5, max_relative = 1e-3);
678 }
679
680 #[test]
681 fn light_year_to_au() {
682 let ly = LightYears::new(1.0);
683 let au = ly.to::<AstronomicalUnit>();
684 assert_relative_eq!(au.value(), 63241.0, max_relative = 1e-3);
686 }
687
688 #[test]
689 fn from_impl_au_to_ly() {
690 let au = 1.0 * AU;
691 let ly: LightYears = au.into();
692 assert_relative_eq!(ly.value(), 1.582e-5, max_relative = 1e-3);
693 }
694
695 #[test]
696 fn from_impl_ly_to_au() {
697 let ly = 1.0 * LY;
698 let au: AstronomicalUnits = ly.into();
699 assert_relative_eq!(au.value(), 63241.0, max_relative = 1e-3);
700 }
701
702 #[test]
707 fn parsec_to_light_year() {
708 let pc = Parsecs::new(1.0);
709 let ly = pc.to::<LightYear>();
710 let expected = (AstronomicalUnit::RATIO * (648_000.0 / PI)) / LightYear::RATIO;
712 assert_relative_eq!(ly.value(), expected, max_relative = 1e-15);
713 }
714
715 #[test]
716 fn parsec_to_au() {
717 let pc = Parsecs::new(1.0);
718 let au = pc.to::<AstronomicalUnit>();
719 assert_relative_eq!(au.value(), 3.26 * 63241.0, max_relative = 1e-2);
722 }
723
724 #[test]
725 fn parsec_ratio_sanity() {
726 let lhs = Parsec::RATIO / AstronomicalUnit::RATIO;
728 let rhs = 648_000.0 / PI;
729 assert_relative_eq!(lhs, rhs, max_relative = 1e-12);
730 }
731
732 #[test]
737 fn solar_radius_to_meters() {
738 let sr = SolarRadiuses::new(1.0);
739 let m = sr.to::<Meter>();
740 assert_abs_diff_eq!(m.value(), 695_700_000.0, epsilon = 1e-3);
742 }
743
744 #[test]
745 fn solar_radius_to_km() {
746 let sr = SolarRadiuses::new(1.0);
747 let km = sr.to::<Kilometer>();
748 assert_abs_diff_eq!(km.value(), 695_700.0, epsilon = 1e-6);
750 }
751
752 #[test]
757 fn roundtrip_km_m() {
758 let original = Kilometers::new(42.5);
759 let converted = original.to::<Meter>();
760 let back = converted.to::<Kilometer>();
761 assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-12);
762 }
763
764 #[test]
765 fn roundtrip_au_ly() {
766 let original = AstronomicalUnits::new(10000.0);
767 let converted = original.to::<LightYear>();
768 let back = converted.to::<AstronomicalUnit>();
769 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
770 }
771
772 #[test]
773 fn roundtrip_parsec_ly() {
774 let original = Parsecs::new(5.0);
775 let converted = original.to::<LightYear>();
776 let back = converted.to::<Parsec>();
777 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
778 }
779
780 #[test]
785 fn inch_to_meter_exact_ratio() {
786 let inch = Inches::new(1.0);
787 let m = inch.to::<Meter>();
788 assert_relative_eq!(m.value(), 0.0254, max_relative = 1e-16);
790 }
791
792 #[test]
793 fn nautical_mile_to_meter_exact_ratio() {
794 let nmi = NauticalMiles::new(1.0);
795 let m = nmi.to::<Meter>();
796 assert_abs_diff_eq!(m.value(), 1852.0, epsilon = 1e-12);
798 }
799
800 #[test]
805 fn roundtrip_inch_meter() {
806 let original = Inches::new(123.456);
807 let converted = original.to::<Meter>();
808 let back = converted.to::<Inch>();
809 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
810 }
811
812 #[test]
813 fn roundtrip_nautical_mile_meter() {
814 let original = NauticalMiles::new(3.75);
815 let converted = original.to::<Meter>();
816 let back = converted.to::<NauticalMile>();
817 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
818 }
819
820 #[test]
821 fn roundtrip_parsec_kpc() {
822 let original = Parsecs::new(12_345.0);
823 let converted = original.to::<Kiloparsec>();
824 let back = converted.to::<Parsec>();
825 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
826 }
827
828 proptest! {
833 #[test]
834 fn prop_roundtrip_km_m(k in -1e6..1e6f64) {
835 let original = Kilometers::new(k);
836 let converted = original.to::<Meter>();
837 let back = converted.to::<Kilometer>();
838 prop_assert!((back.value() - original.value()).abs() < 1e-9 * k.abs().max(1.0));
839 }
840
841 #[test]
842 fn prop_km_m_ratio(k in 1e-6..1e6f64) {
843 let km = Kilometers::new(k);
844 let m = km.to::<Meter>();
845 prop_assert!((m.value() / km.value() - 1000.0).abs() < 1e-9);
847 }
848
849 #[test]
850 fn prop_roundtrip_au_km(a in 1e-6..1e6f64) {
851 let original = AstronomicalUnits::new(a);
852 let converted = original.to::<Kilometer>();
853 let back = converted.to::<AstronomicalUnit>();
854 prop_assert!((back.value() - original.value()).abs() / original.value() < 1e-12);
855 }
856
857 #[test]
858 fn prop_roundtrip_inch_m(i in -1e6..1e6f64) {
859 let original = Inches::new(i);
860 let converted = original.to::<Meter>();
861 let back = converted.to::<Inch>();
862 let scale = i.abs().max(1.0);
863 prop_assert!((back.value() - original.value()).abs() < 1e-9 * scale);
864 }
865 }
866}