1use crate::{Dimension, Quantity, Unit};
38use core::f64::consts::PI;
39use qtty_derive::Unit;
40
41pub enum Length {}
43impl Dimension for Length {}
44
45pub trait LengthUnit: Unit<Dim = Length> {}
47impl<T: Unit<Dim = Length>> LengthUnit for T {}
48
49#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
55#[unit(symbol = "m", dimension = Length, ratio = 1.0)]
56pub struct Meter;
57pub type Meters = Quantity<Meter>;
59pub const M: Meters = Meters::new(1.0);
61
62#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
64#[unit(symbol = "Km", dimension = Length, ratio = 1_000.0)]
65pub struct Kilometer;
66pub type Km = Kilometer;
68pub type Kilometers = Quantity<Km>;
70pub const KM: Kilometers = Kilometers::new(1.0);
72
73#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
75#[unit(symbol = "cm", dimension = Length, ratio = 1e-2)]
76pub struct Centimeter;
77pub type Cm = Centimeter;
79pub type Centimeters = Quantity<Cm>;
81pub const CM: Centimeters = Centimeters::new(1.0);
83
84#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
86#[unit(symbol = "mm", dimension = Length, ratio = 1e-3)]
87pub struct Millimeter;
88pub type Mm = Millimeter;
90pub type Millimeters = Quantity<Mm>;
92pub const MM: Millimeters = Millimeters::new(1.0);
94
95#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
97#[unit(symbol = "um", dimension = Length, ratio = 1e-6)]
98pub struct Micrometer;
99pub type Um = Micrometer;
101pub type Micrometers = Quantity<Um>;
103pub const UM: Micrometers = Micrometers::new(1.0);
105
106#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
108#[unit(symbol = "nm", dimension = Length, ratio = 1e-9)]
109pub struct Nanometer;
110pub type Nm = Nanometer;
112pub type Nanometers = Quantity<Nm>;
114pub const NM: Nanometers = Nanometers::new(1.0);
116
117#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
119#[unit(symbol = "pm", dimension = Length, ratio = 1e-12)]
120pub struct Picometer;
121pub type Picometers = Quantity<Picometer>;
123pub const PMETER: Picometers = Picometers::new(1.0);
125
126#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
128#[unit(symbol = "fm", dimension = Length, ratio = 1e-15)]
129pub struct Femtometer;
130pub type Femtometers = Quantity<Femtometer>;
132pub const FM: Femtometers = Femtometers::new(1.0);
134
135#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
137#[unit(symbol = "am", dimension = Length, ratio = 1e-18)]
138pub struct Attometer;
139pub type Attometers = Quantity<Attometer>;
141pub const AM: Attometers = Attometers::new(1.0);
143
144#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
146#[unit(symbol = "zm", dimension = Length, ratio = 1e-21)]
147pub struct Zeptometer;
148pub type Zeptometers = Quantity<Zeptometer>;
150pub const ZMETER: Zeptometers = Zeptometers::new(1.0);
152
153#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
155#[unit(symbol = "ym", dimension = Length, ratio = 1e-24)]
156pub struct Yoctometer;
157pub type Yoctometers = Quantity<Yoctometer>;
159pub const YMETER: Yoctometers = Yoctometers::new(1.0);
161
162#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
164#[unit(symbol = "Mm", dimension = Length, ratio = 1e6)]
165pub struct Megameter;
166pub type MegaMeter = Megameter;
168pub type Megameters = Quantity<Megameter>;
170pub const MEGAMETER: Megameters = Megameters::new(1.0);
172
173#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
175#[unit(symbol = "dm", dimension = Length, ratio = 1e-1)]
176pub struct Decimeter;
177pub type Decimeters = Quantity<Decimeter>;
179pub const DM: Decimeters = Decimeters::new(1.0);
181
182#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
184#[unit(symbol = "dam", dimension = Length, ratio = 1e1)]
185pub struct Decameter;
186pub type Decameters = Quantity<Decameter>;
188pub const DAM: Decameters = Decameters::new(1.0);
190
191#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
193#[unit(symbol = "hm", dimension = Length, ratio = 1e2)]
194pub struct Hectometer;
195pub type Hectometers = Quantity<Hectometer>;
197pub const HM: Hectometers = Hectometers::new(1.0);
199
200#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
202#[unit(symbol = "Gm", dimension = Length, ratio = 1e9)]
203pub struct Gigameter;
204pub type Gigameters = Quantity<Gigameter>;
206pub const GM: Gigameters = Gigameters::new(1.0);
208
209#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
211#[unit(symbol = "Tm", dimension = Length, ratio = 1e12)]
212pub struct Terameter;
213pub type Terameters = Quantity<Terameter>;
215pub const TM: Terameters = Terameters::new(1.0);
217
218#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
220#[unit(symbol = "Pm", dimension = Length, ratio = 1e15)]
221pub struct Petameter;
222pub type Petameters = Quantity<Petameter>;
224pub const PM: Petameters = Petameters::new(1.0);
226
227#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
229#[unit(symbol = "Em", dimension = Length, ratio = 1e18)]
230pub struct Exameter;
231pub type Exameters = Quantity<Exameter>;
233pub const EM: Exameters = Exameters::new(1.0);
235
236#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
238#[unit(symbol = "Zm", dimension = Length, ratio = 1e21)]
239pub struct Zettameter;
240pub type Zettameters = Quantity<Zettameter>;
242pub const ZM: Zettameters = Zettameters::new(1.0);
244
245#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
247#[unit(symbol = "Ym", dimension = Length, ratio = 1e24)]
248pub struct Yottameter;
249pub type Yottameters = Quantity<Yottameter>;
251pub const YM: Yottameters = Yottameters::new(1.0);
253
254#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
260#[unit(symbol = "au", dimension = Length, ratio = 149_597_870_700.0)]
261pub struct AstronomicalUnit;
262pub type Au = AstronomicalUnit;
264pub type AstronomicalUnits = Quantity<Au>;
266pub const AU: AstronomicalUnits = AstronomicalUnits::new(1.0);
268
269const SPEED_OF_LIGHT_M_PER_S: f64 = 299_792_458.0;
271const SECONDS_PER_DAY: f64 = 86_400.0;
272const DAYS_PER_JULIAN_YEAR: f64 = 36525.0 / 100.0; const SECONDS_PER_JULIAN_YEAR: f64 = SECONDS_PER_DAY * DAYS_PER_JULIAN_YEAR;
274const METERS_PER_LIGHT_YEAR: f64 = SPEED_OF_LIGHT_M_PER_S * SECONDS_PER_JULIAN_YEAR;
275
276#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
278#[unit(symbol = "ly", dimension = Length, ratio = METERS_PER_LIGHT_YEAR)]
279pub struct LightYear;
280pub type Ly = LightYear;
282pub type LightYears = Quantity<Ly>;
284pub const LY: LightYears = LightYears::new(1.0);
286
287#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
289#[unit(symbol = "pc", dimension = Length, ratio = 149_597_870_700.0 * (648_000.0 / PI))]
290pub struct Parsec;
291pub type Pc = Parsec;
293pub type Parsecs = Quantity<Pc>;
295pub const PC: Parsecs = Parsecs::new(1.0);
297
298#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
300#[unit(symbol = "kpc", dimension = Length, ratio = 1_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
301pub struct Kiloparsec;
302pub type Kiloparsecs = Quantity<Kiloparsec>;
304pub const KPC: Kiloparsecs = Kiloparsecs::new(1.0);
306
307#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
309#[unit(symbol = "Mpc", dimension = Length, ratio = 1_000_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
310pub struct Megaparsec;
311pub type Megaparsecs = Quantity<Megaparsec>;
313pub const MPC: Megaparsecs = Megaparsecs::new(1.0);
315
316#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
318#[unit(symbol = "Gpc", dimension = Length, ratio = 1_000_000_000.0 * 149_597_870_700.0 * (648_000.0 / PI))]
319pub struct Gigaparsec;
320pub type Gigaparsecs = Quantity<Gigaparsec>;
322pub const GPC: Gigaparsecs = Gigaparsecs::new(1.0);
324
325#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
331#[unit(symbol = "in", dimension = Length, ratio = 254.0 / 10_000.0)]
332pub struct Inch;
333pub type Inches = Quantity<Inch>;
335pub const INCH: Inches = Inches::new(1.0);
337
338#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
340#[unit(symbol = "ft", dimension = Length, ratio = 3048.0 / 10_000.0)]
341pub struct Foot;
342pub type Feet = Quantity<Foot>;
344pub const FT: Feet = Feet::new(1.0);
346
347#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
349#[unit(symbol = "yd", dimension = Length, ratio = 9144.0 / 10_000.0)]
350pub struct Yard;
351pub type Yards = Quantity<Yard>;
353pub const YD: Yards = Yards::new(1.0);
355
356#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
358#[unit(symbol = "mi", dimension = Length, ratio = 1_609_344.0 / 1_000.0)]
359pub struct Mile;
360pub type Miles = Quantity<Mile>;
362pub const MI: Miles = Miles::new(1.0);
364
365#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
367#[unit(symbol = "nmi", dimension = Length, ratio = 1_852.0)]
368pub struct NauticalMile;
369pub type NauticalMiles = Quantity<NauticalMile>;
371pub const NMI: NauticalMiles = NauticalMiles::new(1.0);
373
374#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
376#[unit(symbol = "ch", dimension = Length, ratio = 66.0 * (3048.0 / 10_000.0))]
377pub struct Chain;
378pub type Chains = Quantity<Chain>;
380pub const CHAIN: Chains = Chains::new(1.0);
382
383#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
385#[unit(symbol = "rd", dimension = Length, ratio = 16.5 * (3048.0 / 10_000.0))]
386pub struct Rod;
387pub type Rods = Quantity<Rod>;
389pub const ROD: Rods = Rods::new(1.0);
391
392#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
394#[unit(symbol = "lk", dimension = Length, ratio = (66.0 / 100.0) * (3048.0 / 10_000.0))]
395pub struct Link;
396pub type Links = Quantity<Link>;
398pub const LINK: Links = Links::new(1.0);
400
401#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
403#[unit(symbol = "ftm", dimension = Length, ratio = 6.0 * (3048.0 / 10_000.0))]
404pub struct Fathom;
405pub type Fathoms = Quantity<Fathom>;
407pub const FTM: Fathoms = Fathoms::new(1.0);
409
410#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
416#[unit(symbol = "Cmer", dimension = Length, ratio = 40_007_863.0)]
417pub struct EarthMeridionalCircumference;
418pub type EarthMeridionalCircumferences = Quantity<EarthMeridionalCircumference>;
420pub const C_MERIDIONAL: EarthMeridionalCircumferences = EarthMeridionalCircumferences::new(1.0);
422
423#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
425#[unit(symbol = "Ceq", dimension = Length, ratio = 40_075_017.0)]
426pub struct EarthEquatorialCircumference;
427pub type EarthEquatorialCircumferences = Quantity<EarthEquatorialCircumference>;
429pub const C_EQUATORIAL: EarthEquatorialCircumferences = EarthEquatorialCircumferences::new(1.0);
431
432#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
438#[unit(symbol = "a0", dimension = Length, ratio = 5.291_772_109_03e-11)]
439pub struct BohrRadius;
440pub type BohrRadii = Quantity<BohrRadius>;
442pub const A0: BohrRadii = BohrRadii::new(1.0);
444
445#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
447#[unit(symbol = "re", dimension = Length, ratio = 2.817_940_326_2e-15)]
448pub struct ClassicalElectronRadius;
449pub type ClassicalElectronRadii = Quantity<ClassicalElectronRadius>;
451pub const RE: ClassicalElectronRadii = ClassicalElectronRadii::new(1.0);
453
454#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
456#[unit(symbol = "lp", dimension = Length, ratio = 1.616_255e-35)]
457pub struct PlanckLength;
458pub type PlanckLengths = Quantity<PlanckLength>;
460pub const LP: PlanckLengths = PlanckLengths::new(1.0);
462
463#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
465#[unit(symbol = "lambda_bar_e", dimension = Length, ratio = 3.861_592_679_6e-13)]
466pub struct ElectronReducedComptonWavelength;
467pub type ElectronReducedComptonWavelengths = Quantity<ElectronReducedComptonWavelength>;
469pub const LAMBDA_BAR_E: ElectronReducedComptonWavelengths =
471 ElectronReducedComptonWavelengths::new(1.0);
472
473pub mod nominal {
482 use super::*;
483
484 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
486 #[unit(symbol = "Rsun", dimension = Length, ratio = 695_700_000.0)]
487 pub struct SolarRadius;
488 pub type SolarRadiuses = Quantity<SolarRadius>;
490 pub const RSUN: SolarRadiuses = SolarRadiuses::new(1.0);
492
493 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
495 #[unit(symbol = "Rearth", dimension = Length, ratio = 6_371_000.0)]
496 pub struct EarthRadius;
497 pub type EarthRadii = Quantity<EarthRadius>;
499 pub const R_EARTH: EarthRadii = EarthRadii::new(1.0);
501
502 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
504 #[unit(symbol = "Rearth_eq", dimension = Length, ratio = 6_378_137.0)]
505 pub struct EarthEquatorialRadius;
506 pub type EarthEquatorialRadii = Quantity<EarthEquatorialRadius>;
508 pub const R_EARTH_EQ: EarthEquatorialRadii = EarthEquatorialRadii::new(1.0);
510
511 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
513 #[unit(symbol = "Rearth_p", dimension = Length, ratio = 6_356_752.314_2)]
514 pub struct EarthPolarRadius;
515 pub type EarthPolarRadii = Quantity<EarthPolarRadius>;
517 pub const R_EARTH_P: EarthPolarRadii = EarthPolarRadii::new(1.0);
519
520 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
522 #[unit(symbol = "Rmoon", dimension = Length, ratio = 1_737_400.0)]
523 pub struct LunarRadius;
524 pub type LunarRadii = Quantity<LunarRadius>;
526 pub const R_MOON: LunarRadii = LunarRadii::new(1.0);
528
529 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
531 #[unit(symbol = "Rjup", dimension = Length, ratio = 71_492_000.0)]
532 pub struct JupiterRadius;
533 pub type JupiterRadii = Quantity<JupiterRadius>;
535 pub const R_JUPITER: JupiterRadii = JupiterRadii::new(1.0);
537
538 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
540 #[unit(symbol = "LD", dimension = Length, ratio = 384_400_000.0)]
541 pub struct LunarDistance;
542 pub type LunarDistances = Quantity<LunarDistance>;
544 pub const LD: LunarDistances = LunarDistances::new(1.0);
546
547 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
549 #[unit(symbol = "Dsun", dimension = Length, ratio = 2.0 * 695_700_000.0)]
550 pub struct SolarDiameter;
551 pub type SolarDiameters = Quantity<SolarDiameter>;
553 pub const D_SUN: SolarDiameters = SolarDiameters::new(1.0);
555
556 crate::impl_unit_conversions!(SolarRadius, Kilometer);
560}
561
562crate::impl_unit_conversions!(
568 Meter,
569 Decimeter,
570 Centimeter,
571 Millimeter,
572 Micrometer,
573 Nanometer,
574 Picometer,
575 Femtometer,
576 Attometer,
577 Zeptometer,
578 Yoctometer,
579 Decameter,
580 Hectometer,
581 Kilometer,
582 Megameter,
583 Gigameter,
584 Terameter,
585 Petameter,
586 Exameter,
587 Zettameter,
588 Yottameter,
589 AstronomicalUnit,
590 LightYear,
591 Parsec,
592 Kiloparsec,
593 Megaparsec,
594 Gigaparsec,
595 Inch,
596 Foot,
597 Yard,
598 Mile,
599 NauticalMile,
600 Chain,
601 Rod,
602 Link,
603 Fathom,
604 EarthMeridionalCircumference,
605 EarthEquatorialCircumference,
606 BohrRadius,
607 ClassicalElectronRadius,
608 PlanckLength,
609 ElectronReducedComptonWavelength
610);
611
612#[cfg(test)]
613mod tests {
614 use super::nominal::SolarRadiuses;
615 use super::*;
616 use approx::{assert_abs_diff_eq, assert_relative_eq};
617 use proptest::prelude::*;
618
619 #[test]
624 fn kilometer_to_meter() {
625 let km = Kilometers::new(1.0);
626 let m = km.to::<Meter>();
627 assert_abs_diff_eq!(m.value(), 1000.0, epsilon = 1e-9);
628 }
629
630 #[test]
631 fn meter_to_kilometer() {
632 let m = Meters::new(1000.0);
633 let km = m.to::<Kilometer>();
634 assert_abs_diff_eq!(km.value(), 1.0, epsilon = 1e-12);
635 }
636
637 #[test]
638 fn au_to_meters() {
639 let au = AstronomicalUnits::new(1.0);
640 let m = au.to::<Meter>();
641 assert_abs_diff_eq!(m.value(), 149_597_870_700.0, epsilon = 1e-6);
643 }
644
645 #[test]
646 fn au_to_kilometers() {
647 let au = AstronomicalUnits::new(1.0);
648 let km = au.to::<Kilometer>();
649 assert_relative_eq!(km.value(), 149_597_870.7, max_relative = 1e-12);
651 }
652
653 #[test]
654 fn light_year_to_meters() {
655 let ly = LightYears::new(1.0);
656 let m = ly.to::<Meter>();
657 assert_relative_eq!(m.value(), METERS_PER_LIGHT_YEAR, max_relative = 1e-12);
659 }
660
661 #[test]
662 fn light_year_to_kilometers() {
663 let ly = LightYears::new(1.0);
664 let km = ly.to::<Kilometer>();
665 assert_relative_eq!(km.value(), 9_460_730_472_580.000_8, max_relative = 1e-9);
667 }
668
669 #[test]
674 fn au_to_light_year() {
675 let au = AstronomicalUnits::new(1.0);
676 let ly = au.to::<LightYear>();
677 assert_relative_eq!(ly.value(), 1.582e-5, max_relative = 1e-3);
679 }
680
681 #[test]
682 fn light_year_to_au() {
683 let ly = LightYears::new(1.0);
684 let au = ly.to::<AstronomicalUnit>();
685 assert_relative_eq!(au.value(), 63241.0, max_relative = 1e-3);
687 }
688
689 #[test]
690 fn from_impl_au_to_ly() {
691 let au = 1.0 * AU;
692 let ly: LightYears = au.into();
693 assert_relative_eq!(ly.value(), 1.582e-5, max_relative = 1e-3);
694 }
695
696 #[test]
697 fn from_impl_ly_to_au() {
698 let ly = 1.0 * LY;
699 let au: AstronomicalUnits = ly.into();
700 assert_relative_eq!(au.value(), 63241.0, max_relative = 1e-3);
701 }
702
703 #[test]
708 fn parsec_to_light_year() {
709 let pc = Parsecs::new(1.0);
710 let ly = pc.to::<LightYear>();
711 let expected = (AstronomicalUnit::RATIO * (648_000.0 / PI)) / LightYear::RATIO;
713 assert_relative_eq!(ly.value(), expected, max_relative = 1e-15);
714 }
715
716 #[test]
717 fn parsec_to_au() {
718 let pc = Parsecs::new(1.0);
719 let au = pc.to::<AstronomicalUnit>();
720 assert_relative_eq!(au.value(), 3.26 * 63241.0, max_relative = 1e-2);
723 }
724
725 #[test]
726 fn parsec_ratio_sanity() {
727 let lhs = Parsec::RATIO / AstronomicalUnit::RATIO;
729 let rhs = 648_000.0 / PI;
730 assert_relative_eq!(lhs, rhs, max_relative = 1e-12);
731 }
732
733 #[test]
738 fn solar_radius_to_meters() {
739 let sr = SolarRadiuses::new(1.0);
740 let m = sr.to::<Meter>();
741 assert_abs_diff_eq!(m.value(), 695_700_000.0, epsilon = 1e-3);
743 }
744
745 #[test]
746 fn solar_radius_to_km() {
747 let sr = SolarRadiuses::new(1.0);
748 let km = sr.to::<Kilometer>();
749 assert_abs_diff_eq!(km.value(), 695_700.0, epsilon = 1e-6);
751 }
752
753 #[test]
758 fn roundtrip_km_m() {
759 let original = Kilometers::new(42.5);
760 let converted = original.to::<Meter>();
761 let back = converted.to::<Kilometer>();
762 assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-12);
763 }
764
765 #[test]
766 fn roundtrip_au_ly() {
767 let original = AstronomicalUnits::new(10000.0);
768 let converted = original.to::<LightYear>();
769 let back = converted.to::<AstronomicalUnit>();
770 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
771 }
772
773 #[test]
774 fn roundtrip_parsec_ly() {
775 let original = Parsecs::new(5.0);
776 let converted = original.to::<LightYear>();
777 let back = converted.to::<Parsec>();
778 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
779 }
780
781 #[test]
786 fn inch_to_meter_exact_ratio() {
787 let inch = Inches::new(1.0);
788 let m = inch.to::<Meter>();
789 assert_relative_eq!(m.value(), 0.0254, max_relative = 1e-16);
791 }
792
793 #[test]
794 fn nautical_mile_to_meter_exact_ratio() {
795 let nmi = NauticalMiles::new(1.0);
796 let m = nmi.to::<Meter>();
797 assert_abs_diff_eq!(m.value(), 1852.0, epsilon = 1e-12);
799 }
800
801 #[test]
806 fn roundtrip_inch_meter() {
807 let original = Inches::new(123.456);
808 let converted = original.to::<Meter>();
809 let back = converted.to::<Inch>();
810 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
811 }
812
813 #[test]
814 fn roundtrip_nautical_mile_meter() {
815 let original = NauticalMiles::new(3.75);
816 let converted = original.to::<Meter>();
817 let back = converted.to::<NauticalMile>();
818 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
819 }
820
821 #[test]
822 fn roundtrip_parsec_kpc() {
823 let original = Parsecs::new(12_345.0);
824 let converted = original.to::<Kiloparsec>();
825 let back = converted.to::<Parsec>();
826 assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
827 }
828
829 proptest! {
834 #[test]
835 fn prop_roundtrip_km_m(k in -1e6..1e6f64) {
836 let original = Kilometers::new(k);
837 let converted = original.to::<Meter>();
838 let back = converted.to::<Kilometer>();
839 prop_assert!((back.value() - original.value()).abs() < 1e-9 * k.abs().max(1.0));
840 }
841
842 #[test]
843 fn prop_km_m_ratio(k in 1e-6..1e6f64) {
844 let km = Kilometers::new(k);
845 let m = km.to::<Meter>();
846 prop_assert!((m.value() / km.value() - 1000.0).abs() < 1e-9);
848 }
849
850 #[test]
851 fn prop_roundtrip_au_km(a in 1e-6..1e6f64) {
852 let original = AstronomicalUnits::new(a);
853 let converted = original.to::<Kilometer>();
854 let back = converted.to::<AstronomicalUnit>();
855 prop_assert!((back.value() - original.value()).abs() / original.value() < 1e-12);
856 }
857
858 #[test]
859 fn prop_roundtrip_inch_m(i in -1e6..1e6f64) {
860 let original = Inches::new(i);
861 let converted = original.to::<Meter>();
862 let back = converted.to::<Inch>();
863 let scale = i.abs().max(1.0);
864 prop_assert!((back.value() - original.value()).abs() < 1e-9 * scale);
865 }
866 }
867}