1use crate::{Quantity, Unit};
82use core::f64::consts::PI;
83use qtty_derive::Unit;
84
85pub use crate::dimension::Length;
87
88pub trait LengthUnit: Unit<Dim = Length> {}
90impl<T: Unit<Dim = Length>> LengthUnit for T {}
91
92#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
98#[unit(symbol = "m", dimension = Length, ratio = 1.0)]
99pub struct Meter;
100pub type Meters = Quantity<Meter>;
102pub const M: Meters = Meters::new(1.0);
104
105#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
107#[unit(symbol = "km", dimension = Length, ratio = 1_000.0)]
108pub struct Kilometer;
109pub type Km = Kilometer;
111pub type Kilometers = Quantity<Km>;
113pub const KM: Kilometers = Kilometers::new(1.0);
115
116#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
118#[unit(symbol = "cm", dimension = Length, ratio = 1e-2)]
119pub struct Centimeter;
120pub type Cm = Centimeter;
122pub type Centimeters = Quantity<Cm>;
124pub const CM: Centimeters = Centimeters::new(1.0);
126
127#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
129#[unit(symbol = "mm", dimension = Length, ratio = 1e-3)]
130pub struct Millimeter;
131pub type Mm = Millimeter;
133pub type Millimeters = Quantity<Mm>;
135pub const MM: Millimeters = Millimeters::new(1.0);
137
138#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
140#[unit(symbol = "μm", dimension = Length, ratio = 1e-6)]
141pub struct Micrometer;
142pub type Um = Micrometer;
144pub type Micrometers = Quantity<Um>;
146pub const UM: Micrometers = Micrometers::new(1.0);
148
149#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
151#[unit(symbol = "nm", dimension = Length, ratio = 1e-9)]
152pub struct Nanometer;
153pub type Nm = Nanometer;
155pub type Nanometers = Quantity<Nm>;
157pub const NM: Nanometers = Nanometers::new(1.0);
159
160#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
162#[unit(symbol = "pm", dimension = Length, ratio = 1e-12)]
163pub struct Picometer;
164pub type Picometers = Quantity<Picometer>;
166pub const PMETER: Picometers = Picometers::new(1.0);
168
169#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
171#[unit(symbol = "fm", dimension = Length, ratio = 1e-15)]
172pub struct Femtometer;
173pub type Femtometers = Quantity<Femtometer>;
175pub const FM: Femtometers = Femtometers::new(1.0);
177
178#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
180#[unit(symbol = "am", dimension = Length, ratio = 1e-18)]
181pub struct Attometer;
182pub type Attometers = Quantity<Attometer>;
184pub const AM: Attometers = Attometers::new(1.0);
186
187#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
189#[unit(symbol = "zm", dimension = Length, ratio = 1e-21)]
190pub struct Zeptometer;
191pub type Zeptometers = Quantity<Zeptometer>;
193pub const ZMETER: Zeptometers = Zeptometers::new(1.0);
195
196#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
198#[unit(symbol = "ym", dimension = Length, ratio = 1e-24)]
199pub struct Yoctometer;
200pub type Yoctometers = Quantity<Yoctometer>;
202pub const YMETER: Yoctometers = Yoctometers::new(1.0);
204
205#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
207#[unit(symbol = "Mm", dimension = Length, ratio = 1e6)]
208pub struct Megameter;
209pub type MegaMeter = Megameter;
211pub type Megameters = Quantity<Megameter>;
213pub const MEGAMETER: Megameters = Megameters::new(1.0);
215
216#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
218#[unit(symbol = "dm", dimension = Length, ratio = 1e-1)]
219pub struct Decimeter;
220pub type Decimeters = Quantity<Decimeter>;
222pub const DM: Decimeters = Decimeters::new(1.0);
224
225#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
227#[unit(symbol = "dam", dimension = Length, ratio = 1e1)]
228pub struct Decameter;
229pub type Decameters = Quantity<Decameter>;
231pub const DAM: Decameters = Decameters::new(1.0);
233
234#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
236#[unit(symbol = "hm", dimension = Length, ratio = 1e2)]
237pub struct Hectometer;
238pub type Hectometers = Quantity<Hectometer>;
240pub const HM: Hectometers = Hectometers::new(1.0);
242
243#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
245#[unit(symbol = "Gm", dimension = Length, ratio = 1e9)]
246pub struct Gigameter;
247pub type Gigameters = Quantity<Gigameter>;
249pub const GM: Gigameters = Gigameters::new(1.0);
251
252#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
254#[unit(symbol = "Tm", dimension = Length, ratio = 1e12)]
255pub struct Terameter;
256pub type Terameters = Quantity<Terameter>;
258pub const TM: Terameters = Terameters::new(1.0);
260
261#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
263#[unit(symbol = "Pm", dimension = Length, ratio = 1e15)]
264pub struct Petameter;
265pub type Petameters = Quantity<Petameter>;
267pub const PM: Petameters = Petameters::new(1.0);
269
270#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
272#[unit(symbol = "Em", dimension = Length, ratio = 1e18)]
273pub struct Exameter;
274pub type Exameters = Quantity<Exameter>;
276pub const EM: Exameters = Exameters::new(1.0);
278
279#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
281#[unit(symbol = "Zm", dimension = Length, ratio = 1e21)]
282pub struct Zettameter;
283pub type Zettameters = Quantity<Zettameter>;
285pub const ZM: Zettameters = Zettameters::new(1.0);
287
288#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
290#[unit(symbol = "Ym", dimension = Length, ratio = 1e24)]
291pub struct Yottameter;
292pub type Yottameters = Quantity<Yottameter>;
294pub const YM: Yottameters = Yottameters::new(1.0);
296
297#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
303#[unit(symbol = "au", dimension = Length, ratio = 149_597_870_700.0)]
304pub struct AstronomicalUnit;
305pub type Au = AstronomicalUnit;
307pub type AstronomicalUnits = Quantity<Au>;
309pub const AU: AstronomicalUnits = AstronomicalUnits::new(1.0);
311
312const SPEED_OF_LIGHT_M_PER_S: f64 = 299_792_458.0;
314const SECONDS_PER_DAY: f64 = 86_400.0;
315const DAYS_PER_JULIAN_YEAR: f64 = 36525.0 / 100.0; const SECONDS_PER_JULIAN_YEAR: f64 = SECONDS_PER_DAY * DAYS_PER_JULIAN_YEAR;
317const METERS_PER_LIGHT_YEAR: f64 = SPEED_OF_LIGHT_M_PER_S * SECONDS_PER_JULIAN_YEAR;
318
319#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
321#[unit(symbol = "ly", dimension = Length, ratio = METERS_PER_LIGHT_YEAR)]
322pub struct LightYear;
323pub type Ly = LightYear;
325pub type LightYears = Quantity<Ly>;
327pub const LY: LightYears = LightYears::new(1.0);
329
330#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
332#[unit(symbol = "pc", dimension = Length, ratio = 149_597_870_700.0 * (648_000.0 / PI))]
333pub struct Parsec;
334pub type Pc = Parsec;
336pub type Parsecs = Quantity<Pc>;
338pub const PC: Parsecs = Parsecs::new(1.0);
340
341#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
343#[unit(symbol = "kpc", dimension = Length, ratio = 1_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
344pub struct Kiloparsec;
345pub type Kiloparsecs = Quantity<Kiloparsec>;
347pub const KPC: Kiloparsecs = Kiloparsecs::new(1.0);
349
350#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
352#[unit(symbol = "Mpc", dimension = Length, ratio = 1_000_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
353pub struct Megaparsec;
354pub type Megaparsecs = Quantity<Megaparsec>;
356pub const MPC: Megaparsecs = Megaparsecs::new(1.0);
358
359#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
361#[unit(symbol = "Gpc", dimension = Length, ratio = 1_000_000_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
362pub struct Gigaparsec;
363pub type Gigaparsecs = Quantity<Gigaparsec>;
365pub const GPC: Gigaparsecs = Gigaparsecs::new(1.0);
367
368#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
374#[unit(symbol = "in", dimension = Length, ratio = 254.0 / 10_000.0)]
375pub struct Inch;
376pub type Inches = Quantity<Inch>;
378pub const INCH: Inches = Inches::new(1.0);
380
381#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
383#[unit(symbol = "ft", dimension = Length, ratio = 3048.0 / 10_000.0)]
384pub struct Foot;
385pub type Feet = Quantity<Foot>;
387pub const FT: Feet = Feet::new(1.0);
389
390#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
392#[unit(symbol = "yd", dimension = Length, ratio = 9144.0 / 10_000.0)]
393pub struct Yard;
394pub type Yards = Quantity<Yard>;
396pub const YD: Yards = Yards::new(1.0);
398
399#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
401#[unit(symbol = "mi", dimension = Length, ratio = 1_609_344.0 / 1_000.0)]
402pub struct Mile;
403pub type Miles = Quantity<Mile>;
405pub const MI: Miles = Miles::new(1.0);
407
408#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
410#[unit(symbol = "nmi", dimension = Length, ratio = 1_852.0)]
411pub struct NauticalMile;
412pub type NauticalMiles = Quantity<NauticalMile>;
414pub const NMI: NauticalMiles = NauticalMiles::new(1.0);
416
417#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
419#[unit(symbol = "ch", dimension = Length, ratio = 66.0 * (3048.0 / 10_000.0))]
420pub struct Chain;
421pub type Chains = Quantity<Chain>;
423pub const CHAIN: Chains = Chains::new(1.0);
425
426#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
428#[unit(symbol = "rd", dimension = Length, ratio = 16.5 * (3048.0 / 10_000.0))]
429pub struct Rod;
430pub type Rods = Quantity<Rod>;
432pub const ROD: Rods = Rods::new(1.0);
434
435#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
437#[unit(symbol = "lk", dimension = Length, ratio = (66.0 / 100.0) * (3048.0 / 10_000.0))]
438pub struct Link;
439pub type Links = Quantity<Link>;
441pub const LINK: Links = Links::new(1.0);
443
444#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
446#[unit(symbol = "ftm", dimension = Length, ratio = 6.0 * (3048.0 / 10_000.0))]
447pub struct Fathom;
448pub type Fathoms = Quantity<Fathom>;
450pub const FTM: Fathoms = Fathoms::new(1.0);
452
453#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
459#[unit(symbol = "Cmer", dimension = Length, ratio = 40_007_863.0)]
460pub struct EarthMeridionalCircumference;
461pub type EarthMeridionalCircumferences = Quantity<EarthMeridionalCircumference>;
463pub const C_MERIDIONAL: EarthMeridionalCircumferences = EarthMeridionalCircumferences::new(1.0);
465
466#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
468#[unit(symbol = "Ceq", dimension = Length, ratio = 40_075_017.0)]
469pub struct EarthEquatorialCircumference;
470pub type EarthEquatorialCircumferences = Quantity<EarthEquatorialCircumference>;
472pub const C_EQUATORIAL: EarthEquatorialCircumferences = EarthEquatorialCircumferences::new(1.0);
474
475#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
481#[unit(symbol = "a0", dimension = Length, ratio = 5.291_772_109_03e-11)]
482pub struct BohrRadius;
483pub type BohrRadii = Quantity<BohrRadius>;
485pub const A0: BohrRadii = BohrRadii::new(1.0);
487
488#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
490#[unit(symbol = "re", dimension = Length, ratio = 2.817_940_326_2e-15)]
491pub struct ClassicalElectronRadius;
492pub type ClassicalElectronRadii = Quantity<ClassicalElectronRadius>;
494pub const RE: ClassicalElectronRadii = ClassicalElectronRadii::new(1.0);
496
497#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
499#[unit(symbol = "lp", dimension = Length, ratio = 1.616_255e-35)]
500pub struct PlanckLength;
501pub type PlanckLengths = Quantity<PlanckLength>;
503pub const LP: PlanckLengths = PlanckLengths::new(1.0);
505
506#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
508#[unit(symbol = "lambda_bar_e", dimension = Length, ratio = 3.861_592_679_6e-13)]
509pub struct ElectronReducedComptonWavelength;
510pub type ElectronReducedComptonWavelengths = Quantity<ElectronReducedComptonWavelength>;
512pub const LAMBDA_BAR_E: ElectronReducedComptonWavelengths =
514 ElectronReducedComptonWavelengths::new(1.0);
515
516pub mod nominal {
525 use super::*;
526
527 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
529 #[unit(symbol = "Rsun", dimension = Length, ratio = 695_700_000.0)]
530 pub struct SolarRadius;
531 pub type SolarRadiuses = Quantity<SolarRadius>;
533 pub const RSUN: SolarRadiuses = SolarRadiuses::new(1.0);
535
536 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
538 #[unit(symbol = "Rearth", dimension = Length, ratio = 6_371_000.0)]
539 pub struct EarthRadius;
540 pub type EarthRadii = Quantity<EarthRadius>;
542 pub const R_EARTH: EarthRadii = EarthRadii::new(1.0);
544
545 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
547 #[unit(symbol = "Rearth_eq", dimension = Length, ratio = 6_378_137.0)]
548 pub struct EarthEquatorialRadius;
549 pub type EarthEquatorialRadii = Quantity<EarthEquatorialRadius>;
551 pub const R_EARTH_EQ: EarthEquatorialRadii = EarthEquatorialRadii::new(1.0);
553
554 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
556 #[unit(symbol = "Rearth_p", dimension = Length, ratio = 6_356_752.314_2)]
557 pub struct EarthPolarRadius;
558 pub type EarthPolarRadii = Quantity<EarthPolarRadius>;
560 pub const R_EARTH_P: EarthPolarRadii = EarthPolarRadii::new(1.0);
562
563 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
565 #[unit(symbol = "Rmoon", dimension = Length, ratio = 1_737_400.0)]
566 pub struct LunarRadius;
567 pub type LunarRadii = Quantity<LunarRadius>;
569 pub const R_MOON: LunarRadii = LunarRadii::new(1.0);
571
572 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
574 #[unit(symbol = "Rjup", dimension = Length, ratio = 71_492_000.0)]
575 pub struct JupiterRadius;
576 pub type JupiterRadii = Quantity<JupiterRadius>;
578 pub const R_JUPITER: JupiterRadii = JupiterRadii::new(1.0);
580
581 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
583 #[unit(symbol = "LD", dimension = Length, ratio = 384_400_000.0)]
584 pub struct LunarDistance;
585 pub type LunarDistances = Quantity<LunarDistance>;
587 pub const LD: LunarDistances = LunarDistances::new(1.0);
589
590 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
592 #[unit(symbol = "Dsun", dimension = Length, ratio = 2.0 * 695_700_000.0)]
593 pub struct SolarDiameter;
594 pub type SolarDiameters = Quantity<SolarDiameter>;
596 pub const D_SUN: SolarDiameters = SolarDiameters::new(1.0);
598
599 crate::impl_unit_from_conversions!(SolarRadius, Kilometer);
603 #[cfg(feature = "cross-unit-ops")]
604 crate::impl_unit_cross_unit_ops!(SolarRadius, Kilometer);
605}
606
607crate::impl_unit_from_conversions!(
613 Meter,
614 Decimeter,
615 Centimeter,
616 Millimeter,
617 Micrometer,
618 Nanometer,
619 Picometer,
620 Femtometer,
621 Attometer,
622 Zeptometer,
623 Yoctometer,
624 Decameter,
625 Hectometer,
626 Kilometer,
627 Megameter,
628 Gigameter,
629 Terameter,
630 Petameter,
631 Exameter,
632 Zettameter,
633 Yottameter,
634 AstronomicalUnit,
635 LightYear,
636 Parsec,
637 Kiloparsec,
638 Megaparsec,
639 Gigaparsec,
640 Inch,
641 Foot,
642 Yard,
643 Mile,
644 NauticalMile,
645 Chain,
646 Rod,
647 Link,
648 Fathom,
649 EarthMeridionalCircumference,
650 EarthEquatorialCircumference,
651 BohrRadius,
652 ClassicalElectronRadius,
653 PlanckLength,
654 ElectronReducedComptonWavelength
655);
656
657#[cfg(feature = "cross-unit-ops")]
659crate::impl_unit_cross_unit_ops!(
660 Meter,
661 Decimeter,
662 Centimeter,
663 Millimeter,
664 Micrometer,
665 Nanometer,
666 Picometer,
667 Femtometer,
668 Attometer,
669 Zeptometer,
670 Yoctometer,
671 Decameter,
672 Hectometer,
673 Kilometer,
674 Megameter,
675 Gigameter,
676 Terameter,
677 Petameter,
678 Exameter,
679 Zettameter,
680 Yottameter,
681 AstronomicalUnit,
682 LightYear,
683 Parsec,
684 Kiloparsec,
685 Megaparsec,
686 Gigaparsec,
687 Inch,
688 Foot,
689 Yard,
690 Mile,
691 NauticalMile,
692 Chain,
693 Rod,
694 Link,
695 Fathom,
696 EarthMeridionalCircumference,
697 EarthEquatorialCircumference,
698 BohrRadius,
699 ClassicalElectronRadius,
700 PlanckLength,
701 ElectronReducedComptonWavelength
702);
703
704#[cfg(test)]
705mod tests {
706 use super::nominal::SolarRadiuses;
707 use super::*;
708 use approx::{assert_abs_diff_eq, assert_relative_eq};
709 use proptest::prelude::*;
710
711 #[test]
716 fn kilometer_to_meter() {
717 let km = Kilometers::new(1.0);
718 let m = km.to::<Meter>();
719 assert_abs_diff_eq!(m.value(), 1000.0, epsilon = 1e-9);
720 }
721
722 #[test]
723 fn meter_to_kilometer() {
724 let m = Meters::new(1000.0);
725 let km = m.to::<Kilometer>();
726 assert_abs_diff_eq!(km.value(), 1.0, epsilon = 1e-12);
727 }
728
729 #[test]
730 fn au_to_meters() {
731 let au = AstronomicalUnits::new(1.0);
732 let m = au.to::<Meter>();
733 assert_abs_diff_eq!(m.value(), 149_597_870_700.0, epsilon = 1e-6);
735 }
736
737 #[test]
738 fn au_to_kilometers() {
739 let au = AstronomicalUnits::new(1.0);
740 let km = au.to::<Kilometer>();
741 assert_relative_eq!(km.value(), 149_597_870.7, max_relative = 1e-12);
743 }
744
745 #[test]
746 fn light_year_to_meters() {
747 let ly = LightYears::new(1.0);
748 let m = ly.to::<Meter>();
749 assert_relative_eq!(m.value(), METERS_PER_LIGHT_YEAR, max_relative = 1e-12);
751 }
752
753 #[test]
754 fn light_year_to_kilometers() {
755 let ly = LightYears::new(1.0);
756 let km = ly.to::<Kilometer>();
757 assert_relative_eq!(km.value(), 9_460_730_472_580.000_8, max_relative = 1e-9);
759 }
760
761 #[test]
766 fn au_to_light_year() {
767 let au = AstronomicalUnits::new(1.0);
768 let ly = au.to::<LightYear>();
769 assert_relative_eq!(ly.value(), 1.582e-5, max_relative = 1e-3);
771 }
772
773 #[test]
774 fn light_year_to_au() {
775 let ly = LightYears::new(1.0);
776 let au = ly.to::<AstronomicalUnit>();
777 assert_relative_eq!(au.value(), 63241.0, max_relative = 1e-3);
779 }
780
781 #[test]
782 fn from_impl_au_to_ly() {
783 let au = 1.0 * AU;
784 let ly: LightYears = au.into();
785 assert_relative_eq!(ly.value(), 1.582e-5, max_relative = 1e-3);
786 }
787
788 #[test]
789 fn from_impl_ly_to_au() {
790 let ly = 1.0 * LY;
791 let au: AstronomicalUnits = ly.into();
792 assert_relative_eq!(au.value(), 63241.0, max_relative = 1e-3);
793 }
794
795 #[test]
800 fn parsec_to_light_year() {
801 let pc = Parsecs::new(1.0);
802 let ly = pc.to::<LightYear>();
803 let expected = (AstronomicalUnit::RATIO * (648_000.0 / PI)) / LightYear::RATIO;
805 assert_relative_eq!(ly.value(), expected, max_relative = 1e-15);
806 }
807
808 #[test]
809 fn parsec_to_au() {
810 let pc = Parsecs::new(1.0);
811 let au = pc.to::<AstronomicalUnit>();
812 assert_relative_eq!(au.value(), 3.26 * 63241.0, max_relative = 1e-2);
815 }
816
817 #[test]
818 fn parsec_ratio_sanity() {
819 let lhs = Parsec::RATIO / AstronomicalUnit::RATIO;
821 let rhs = 648_000.0 / PI;
822 assert_relative_eq!(lhs, rhs, max_relative = 1e-12);
823 }
824
825 #[test]
830 fn solar_radius_to_meters() {
831 let sr = SolarRadiuses::new(1.0);
832 let m = sr.to::<Meter>();
833 assert_abs_diff_eq!(m.value(), 695_700_000.0, epsilon = 1e-3);
835 }
836
837 #[test]
838 fn solar_radius_to_km() {
839 let sr = SolarRadiuses::new(1.0);
840 let km = sr.to::<Kilometer>();
841 assert_abs_diff_eq!(km.value(), 695_700.0, epsilon = 1e-6);
843 }
844
845 #[test]
850 fn roundtrip_km_m() {
851 let original = Kilometers::new(42.5);
852 let converted = original.to::<Meter>();
853 let back = converted.to::<Kilometer>();
854 assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-12);
855 }
856
857 #[test]
858 fn roundtrip_au_ly() {
859 let original = AstronomicalUnits::new(10000.0);
860 let converted = original.to::<LightYear>();
861 let back = converted.to::<AstronomicalUnit>();
862 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
863 }
864
865 #[test]
866 fn roundtrip_parsec_ly() {
867 let original = Parsecs::new(5.0);
868 let converted = original.to::<LightYear>();
869 let back = converted.to::<Parsec>();
870 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
871 }
872
873 #[test]
878 fn inch_to_meter_exact_ratio() {
879 let inch = Inches::new(1.0);
880 let m = inch.to::<Meter>();
881 assert_relative_eq!(m.value(), 0.0254, max_relative = 1e-16);
883 }
884
885 #[test]
886 fn nautical_mile_to_meter_exact_ratio() {
887 let nmi = NauticalMiles::new(1.0);
888 let m = nmi.to::<Meter>();
889 assert_abs_diff_eq!(m.value(), 1852.0, epsilon = 1e-12);
891 }
892
893 #[test]
898 fn roundtrip_inch_meter() {
899 let original = Inches::new(123.456);
900 let converted = original.to::<Meter>();
901 let back = converted.to::<Inch>();
902 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
903 }
904
905 #[test]
906 fn roundtrip_nautical_mile_meter() {
907 let original = NauticalMiles::new(3.75);
908 let converted = original.to::<Meter>();
909 let back = converted.to::<NauticalMile>();
910 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
911 }
912
913 #[test]
914 fn roundtrip_parsec_kpc() {
915 let original = Parsecs::new(12_345.0);
916 let converted = original.to::<Kiloparsec>();
917 let back = converted.to::<Parsec>();
918 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
919 }
920
921 proptest! {
926 #[test]
927 fn prop_roundtrip_km_m(k in -1e6..1e6f64) {
928 let original = Kilometers::new(k);
929 let converted = original.to::<Meter>();
930 let back = converted.to::<Kilometer>();
931 prop_assert!((back.value() - original.value()).abs() < 1e-9 * k.abs().max(1.0));
932 }
933
934 #[test]
935 fn prop_km_m_ratio(k in 1e-6..1e6f64) {
936 let km = Kilometers::new(k);
937 let m = km.to::<Meter>();
938 prop_assert!((m.value() / km.value() - 1000.0).abs() < 1e-9);
940 }
941
942 #[test]
943 fn prop_roundtrip_au_km(a in 1e-6..1e6f64) {
944 let original = AstronomicalUnits::new(a);
945 let converted = original.to::<Kilometer>();
946 let back = converted.to::<AstronomicalUnit>();
947 prop_assert!((back.value() - original.value()).abs() / original.value() < 1e-12);
948 }
949
950 #[test]
951 fn prop_roundtrip_inch_m(i in -1e6..1e6f64) {
952 let original = Inches::new(i);
953 let converted = original.to::<Meter>();
954 let back = converted.to::<Inch>();
955 let scale = i.abs().max(1.0);
956 prop_assert!((back.value() - original.value()).abs() < 1e-9 * scale);
957 }
958 }
959
960 #[test]
965 fn decimeter_to_meter() {
966 let q = Decimeters::new(10.0);
967 assert_relative_eq!(q.to::<Meter>().value(), 1.0, max_relative = 1e-15);
968 }
969
970 #[test]
971 fn centimeter_to_meter() {
972 let q = Centimeters::new(100.0);
973 assert_relative_eq!(q.to::<Meter>().value(), 1.0, max_relative = 1e-15);
974 }
975
976 #[test]
977 fn millimeter_to_centimeter() {
978 let q = Millimeters::new(10.0);
979 assert_relative_eq!(q.to::<Centimeter>().value(), 1.0, max_relative = 1e-15);
980 }
981
982 #[test]
983 fn micrometer_to_millimeter() {
984 let q = Micrometers::new(1_000.0);
985 assert_relative_eq!(q.to::<Millimeter>().value(), 1.0, max_relative = 1e-15);
986 }
987
988 #[test]
989 fn nanometer_to_micrometer() {
990 let q = Nanometers::new(1_000.0);
991 assert_relative_eq!(q.to::<Micrometer>().value(), 1.0, max_relative = 1e-15);
992 }
993
994 #[test]
995 fn picometer_to_nanometer() {
996 let q = Picometers::new(1_000.0);
997 assert_relative_eq!(q.to::<Nanometer>().value(), 1.0, max_relative = 1e-15);
998 }
999
1000 #[test]
1001 fn femtometer_to_picometer() {
1002 let q = Femtometers::new(1_000.0);
1003 assert_relative_eq!(q.to::<Picometer>().value(), 1.0, max_relative = 1e-15);
1004 }
1005
1006 #[test]
1007 fn attometer_to_femtometer() {
1008 let q = Attometers::new(1_000.0);
1009 assert_relative_eq!(q.to::<Femtometer>().value(), 1.0, max_relative = 1e-15);
1010 }
1011
1012 #[test]
1013 fn zeptometer_to_attometer() {
1014 let q = Zeptometers::new(1_000.0);
1015 assert_relative_eq!(q.to::<Attometer>().value(), 1.0, max_relative = 1e-15);
1016 }
1017
1018 #[test]
1019 fn yoctometer_to_zeptometer() {
1020 let q = Yoctometers::new(1_000.0);
1021 assert_relative_eq!(q.to::<Zeptometer>().value(), 1.0, max_relative = 1e-15);
1022 }
1023
1024 #[test]
1029 fn decameter_to_meter() {
1030 let q = Decameters::new(1.0);
1031 assert_relative_eq!(q.to::<Meter>().value(), 10.0, max_relative = 1e-15);
1032 }
1033
1034 #[test]
1035 fn hectometer_to_meter() {
1036 let q = Hectometers::new(1.0);
1037 assert_relative_eq!(q.to::<Meter>().value(), 100.0, max_relative = 1e-15);
1038 }
1039
1040 #[test]
1041 fn megameter_to_kilometer() {
1042 let q = Megameters::new(1.0);
1043 assert_relative_eq!(q.to::<Kilometer>().value(), 1_000.0, max_relative = 1e-15);
1044 }
1045
1046 #[test]
1047 fn gigameter_to_megameter() {
1048 let q = Gigameters::new(1.0);
1049 assert_relative_eq!(q.to::<Megameter>().value(), 1_000.0, max_relative = 1e-15);
1050 }
1051
1052 #[test]
1053 fn terameter_to_gigameter() {
1054 let q = Terameters::new(1.0);
1055 assert_relative_eq!(q.to::<Gigameter>().value(), 1_000.0, max_relative = 1e-15);
1056 }
1057
1058 #[test]
1059 fn petameter_to_terameter() {
1060 let q = Petameters::new(1.0);
1061 assert_relative_eq!(q.to::<Terameter>().value(), 1_000.0, max_relative = 1e-15);
1062 }
1063
1064 #[test]
1065 fn exameter_to_petameter() {
1066 let q = Exameters::new(1.0);
1067 assert_relative_eq!(q.to::<Petameter>().value(), 1_000.0, max_relative = 1e-15);
1068 }
1069
1070 #[test]
1071 fn zettameter_to_exameter() {
1072 let q = Zettameters::new(1.0);
1073 assert_relative_eq!(q.to::<Exameter>().value(), 1_000.0, max_relative = 1e-15);
1074 }
1075
1076 #[test]
1077 fn yottameter_to_zettameter() {
1078 let q = Yottameters::new(1.0);
1079 assert_relative_eq!(q.to::<Zettameter>().value(), 1_000.0, max_relative = 1e-15);
1080 }
1081
1082 #[test]
1087 fn foot_to_meter() {
1088 let q = Feet::new(1.0);
1089 assert_relative_eq!(q.to::<Meter>().value(), 0.3048, max_relative = 1e-15);
1091 }
1092
1093 #[test]
1094 fn yard_to_meter() {
1095 let q = Yards::new(1.0);
1096 assert_relative_eq!(q.to::<Meter>().value(), 0.9144, max_relative = 1e-15);
1098 }
1099
1100 #[test]
1101 fn mile_to_kilometer() {
1102 let q = Miles::new(1.0);
1103 assert_relative_eq!(q.to::<Kilometer>().value(), 1.609_344, max_relative = 1e-15);
1105 }
1106
1107 #[test]
1108 fn fathom_to_foot() {
1109 let q = Fathoms::new(1.0);
1110 assert_relative_eq!(q.to::<Foot>().value(), 6.0, max_relative = 1e-14);
1112 }
1113
1114 #[test]
1115 fn chain_to_foot() {
1116 let q = Chains::new(1.0);
1117 assert_relative_eq!(q.to::<Foot>().value(), 66.0, max_relative = 1e-14);
1119 }
1120
1121 #[test]
1122 fn rod_to_foot() {
1123 let q = Rods::new(1.0);
1124 assert_relative_eq!(q.to::<Foot>().value(), 16.5, max_relative = 1e-14);
1126 }
1127
1128 #[test]
1129 fn link_to_foot() {
1130 let q = Links::new(100.0);
1131 assert_relative_eq!(q.to::<Foot>().value(), 66.0, max_relative = 1e-14);
1133 }
1134
1135 #[test]
1140 fn megaparsec_to_kiloparsec() {
1141 let q = Megaparsecs::new(1.0);
1142 assert_relative_eq!(q.to::<Kiloparsec>().value(), 1_000.0, max_relative = 1e-12);
1143 }
1144
1145 #[test]
1146 fn gigaparsec_to_megaparsec() {
1147 let q = Gigaparsecs::new(1.0);
1148 assert_relative_eq!(q.to::<Megaparsec>().value(), 1_000.0, max_relative = 1e-12);
1149 }
1150
1151 #[test]
1156 fn earth_meridional_circumference_to_km() {
1157 let q = EarthMeridionalCircumferences::new(1.0);
1158 assert_relative_eq!(q.to::<Kilometer>().value(), 40_007.863, max_relative = 1e-6);
1160 }
1161
1162 #[test]
1163 fn earth_equatorial_circumference_to_km() {
1164 let q = EarthEquatorialCircumferences::new(1.0);
1165 assert_relative_eq!(q.to::<Kilometer>().value(), 40_075.017, max_relative = 1e-6);
1167 }
1168
1169 #[test]
1174 fn bohr_radius_to_picometers() {
1175 let q = BohrRadii::new(1.0);
1176 assert_relative_eq!(q.to::<Picometer>().value(), 52.917_72, max_relative = 1e-5);
1178 }
1179
1180 #[test]
1181 fn classical_electron_radius_to_femtometers() {
1182 let q = ClassicalElectronRadii::new(1.0);
1183 assert_relative_eq!(
1185 q.to::<Femtometer>().value(),
1186 2.817_940_326_2,
1187 max_relative = 1e-9
1188 );
1189 }
1190
1191 #[test]
1192 fn planck_length_ratio() {
1193 let q = PlanckLengths::new(1.0);
1195 let back = q.to::<Meter>().to::<PlanckLength>();
1196 assert_relative_eq!(back.value(), 1.0, max_relative = 1e-9);
1197 }
1198
1199 #[test]
1200 fn electron_compton_wavelength_to_femtometers() {
1201 let q = ElectronReducedComptonWavelengths::new(1.0);
1202 assert_relative_eq!(
1204 q.to::<Femtometer>().value(),
1205 386.159_267_96,
1206 max_relative = 1e-7
1207 );
1208 }
1209
1210 #[test]
1215 fn earth_radius_to_km() {
1216 let q = nominal::EarthRadii::new(1.0);
1217 assert_relative_eq!(q.to::<Kilometer>().value(), 6_371.0, max_relative = 1e-9);
1218 }
1219
1220 #[test]
1221 fn earth_equatorial_radius_to_km() {
1222 let q = nominal::EarthEquatorialRadii::new(1.0);
1223 assert_relative_eq!(q.to::<Kilometer>().value(), 6_378.137, max_relative = 1e-9);
1224 }
1225
1226 #[test]
1227 fn earth_polar_radius_to_km() {
1228 let q = nominal::EarthPolarRadii::new(1.0);
1229 assert_relative_eq!(
1230 q.to::<Kilometer>().value(),
1231 6_356.752_314_2,
1232 max_relative = 1e-9
1233 );
1234 }
1235
1236 #[test]
1237 fn lunar_radius_to_km() {
1238 let q = nominal::LunarRadii::new(1.0);
1239 assert_relative_eq!(q.to::<Kilometer>().value(), 1_737.4, max_relative = 1e-9);
1240 }
1241
1242 #[test]
1243 fn jupiter_radius_to_km() {
1244 let q = nominal::JupiterRadii::new(1.0);
1245 assert_relative_eq!(q.to::<Kilometer>().value(), 71_492.0, max_relative = 1e-9);
1246 }
1247
1248 #[test]
1249 fn lunar_distance_to_km() {
1250 let q = nominal::LunarDistances::new(1.0);
1251 assert_relative_eq!(q.to::<Kilometer>().value(), 384_400.0, max_relative = 1e-9);
1252 }
1253
1254 #[test]
1255 fn solar_diameter_to_solar_radius() {
1256 let diameters = nominal::SolarDiameters::new(1.0);
1257 let radii = diameters.to::<nominal::SolarRadius>();
1258 assert_relative_eq!(radii.value(), 2.0, max_relative = 1e-14);
1259 }
1260
1261 #[test]
1262 fn symbols_are_correct() {
1263 assert_eq!(Meter::SYMBOL, "m");
1264 assert_eq!(Kilometer::SYMBOL, "km");
1265 assert_eq!(Centimeter::SYMBOL, "cm");
1266 assert_eq!(Inch::SYMBOL, "in");
1267 assert_eq!(AstronomicalUnit::SYMBOL, "au");
1268 assert_eq!(Parsec::SYMBOL, "pc");
1269 }
1270}