siderust-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/.github/workflows/ci.yml +166 -0
  2. package/.gitmodules +9 -0
  3. package/CHANGELOG.md +26 -0
  4. package/LICENSE +661 -0
  5. package/README.md +138 -0
  6. package/package.json +12 -0
  7. package/qtty-js/.github/workflows/ci.yml +151 -0
  8. package/qtty-js/.gitmodules +3 -0
  9. package/qtty-js/CHANGELOG.md +31 -0
  10. package/qtty-js/LICENSE +661 -0
  11. package/qtty-js/README.md +132 -0
  12. package/qtty-js/package.json +20 -0
  13. package/qtty-js/qtty/.github/workflows/ci.yml +155 -0
  14. package/qtty-js/qtty/CHANGELOG.md +120 -0
  15. package/qtty-js/qtty/Cargo.lock +1462 -0
  16. package/qtty-js/qtty/Cargo.toml +12 -0
  17. package/qtty-js/qtty/LICENSE +661 -0
  18. package/qtty-js/qtty/README.md +9 -0
  19. package/qtty-js/qtty/qtty/Cargo.toml +41 -0
  20. package/qtty-js/qtty/qtty/README.md +8 -0
  21. package/qtty-js/qtty/qtty/examples/angles.rs +14 -0
  22. package/qtty-js/qtty/qtty/examples/astronomy.rs +17 -0
  23. package/qtty-js/qtty/qtty/examples/dimensional_arithmetic.rs +83 -0
  24. package/qtty-js/qtty/qtty/examples/python_integration.rs +61 -0
  25. package/qtty-js/qtty/qtty/examples/quickstart.rs +15 -0
  26. package/qtty-js/qtty/qtty/examples/ratios.rs +12 -0
  27. package/qtty-js/qtty/qtty/examples/serde_with_unit.rs +234 -0
  28. package/qtty-js/qtty/qtty/examples/serialization.rs +141 -0
  29. package/qtty-js/qtty/qtty/examples/serialization_advanced.rs +155 -0
  30. package/qtty-js/qtty/qtty/src/f32.rs +108 -0
  31. package/qtty-js/qtty/qtty/src/f64.rs +30 -0
  32. package/qtty-js/qtty/qtty/src/i128.rs +111 -0
  33. package/qtty-js/qtty/qtty/src/i16.rs +111 -0
  34. package/qtty-js/qtty/qtty/src/i32.rs +111 -0
  35. package/qtty-js/qtty/qtty/src/i64.rs +111 -0
  36. package/qtty-js/qtty/qtty/src/i8.rs +111 -0
  37. package/qtty-js/qtty/qtty/src/lib.rs +238 -0
  38. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/Cargo.lock +83 -0
  39. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/Cargo.toml +10 -0
  40. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std/src/lib.rs +7 -0
  41. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/Cargo.lock +83 -0
  42. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/Cargo.toml +10 -0
  43. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-no-std-alloc/src/lib.rs +7 -0
  44. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/Cargo.lock +83 -0
  45. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/Cargo.toml +10 -0
  46. package/qtty-js/qtty/qtty/tests/fixtures/qtty-vec-std/src/lib.rs +5 -0
  47. package/qtty-js/qtty/qtty/tests/integration_tests.rs +529 -0
  48. package/qtty-js/qtty/qtty/tests/qtty_vec_feature_matrix.rs +58 -0
  49. package/qtty-js/qtty/qtty-core/Cargo.toml +41 -0
  50. package/qtty-js/qtty/qtty-core/README.md +8 -0
  51. package/qtty-js/qtty/qtty-core/examples/diesel_integration.rs +145 -0
  52. package/qtty-js/qtty/qtty-core/examples/quantity_db_serde.rs +215 -0
  53. package/qtty-js/qtty/qtty-core/src/dimension.rs +249 -0
  54. package/qtty-js/qtty/qtty-core/src/feature_diesel.rs +318 -0
  55. package/qtty-js/qtty/qtty-core/src/feature_pyo3.rs +27 -0
  56. package/qtty-js/qtty/qtty-core/src/feature_serde.rs +203 -0
  57. package/qtty-js/qtty/qtty-core/src/feature_tiberius.rs +28 -0
  58. package/qtty-js/qtty/qtty-core/src/lib.rs +744 -0
  59. package/qtty-js/qtty/qtty-core/src/macros.rs +93 -0
  60. package/qtty-js/qtty/qtty-core/src/quantity.rs +810 -0
  61. package/qtty-js/qtty/qtty-core/src/scalar.rs +1742 -0
  62. package/qtty-js/qtty/qtty-core/src/unit.rs +332 -0
  63. package/qtty-js/qtty/qtty-core/src/units/angular.rs +1228 -0
  64. package/qtty-js/qtty/qtty-core/src/units/area.rs +243 -0
  65. package/qtty-js/qtty/qtty-core/src/units/frequency.rs +179 -0
  66. package/qtty-js/qtty/qtty-core/src/units/length.rs +1270 -0
  67. package/qtty-js/qtty/qtty-core/src/units/mass.rs +488 -0
  68. package/qtty-js/qtty/qtty-core/src/units/mod.rs +26 -0
  69. package/qtty-js/qtty/qtty-core/src/units/power.rs +324 -0
  70. package/qtty-js/qtty/qtty-core/src/units/time.rs +667 -0
  71. package/qtty-js/qtty/qtty-core/src/units/unitless.rs +212 -0
  72. package/qtty-js/qtty/qtty-core/src/units/velocity.rs +210 -0
  73. package/qtty-js/qtty/qtty-core/src/units/volume.rs +269 -0
  74. package/qtty-js/qtty/qtty-core/tests/core.rs +628 -0
  75. package/qtty-js/qtty/qtty-core/tests/diesel.rs +461 -0
  76. package/qtty-js/qtty/qtty-core/tests/integers.rs +632 -0
  77. package/qtty-js/qtty/qtty-core/tests/no_cross_unit_ops.rs +35 -0
  78. package/qtty-js/qtty/qtty-core/tests/pyo3.rs +334 -0
  79. package/qtty-js/qtty/qtty-core/tests/quantity_f32.rs +276 -0
  80. package/qtty-js/qtty/qtty-core/tests/scalar_decimal.rs +258 -0
  81. package/qtty-js/qtty/qtty-core/tests/scalar_f32.rs +286 -0
  82. package/qtty-js/qtty/qtty-core/tests/scalar_f64_real.rs +287 -0
  83. package/qtty-js/qtty/qtty-core/tests/scalar_rational.rs +260 -0
  84. package/qtty-js/qtty/qtty-core/tests/serde.rs +256 -0
  85. package/qtty-js/qtty/qtty-core/tests/tiberius.rs +208 -0
  86. package/qtty-js/qtty/qtty-derive/Cargo.toml +23 -0
  87. package/qtty-js/qtty/qtty-derive/README.md +8 -0
  88. package/qtty-js/qtty/qtty-derive/src/lib.rs +340 -0
  89. package/qtty-js/qtty/qtty-ffi/ARCHITECTURE.md +3 -0
  90. package/qtty-js/qtty/qtty-ffi/Cargo.toml +31 -0
  91. package/qtty-js/qtty/qtty-ffi/README.md +9 -0
  92. package/qtty-js/qtty/qtty-ffi/build.rs +326 -0
  93. package/qtty-js/qtty/qtty-ffi/cbindgen.toml +105 -0
  94. package/qtty-js/qtty/qtty-ffi/include/qtty_ffi.h +1126 -0
  95. package/qtty-js/qtty/qtty-ffi/src/ffi.rs +1251 -0
  96. package/qtty-js/qtty/qtty-ffi/src/ffi_serde.rs +294 -0
  97. package/qtty-js/qtty/qtty-ffi/src/helpers.rs +310 -0
  98. package/qtty-js/qtty/qtty-ffi/src/lib.rs +229 -0
  99. package/qtty-js/qtty/qtty-ffi/src/macros.rs +121 -0
  100. package/qtty-js/qtty/qtty-ffi/src/registry.rs +274 -0
  101. package/qtty-js/qtty/qtty-ffi/src/types.rs +620 -0
  102. package/qtty-js/qtty/qtty-ffi/tests/integration_tests.rs +842 -0
  103. package/qtty-js/qtty/qtty-ffi/units.csv +156 -0
  104. package/qtty-js/qtty/qtty-ffi/units.csv.md +3 -0
  105. package/qtty-js/qtty-node/.prettierignore +6 -0
  106. package/qtty-js/qtty-node/.prettierrc.json +6 -0
  107. package/qtty-js/qtty-node/README.md +250 -0
  108. package/qtty-js/qtty-node/c8.config.json +11 -0
  109. package/qtty-js/qtty-node/eslint.config.js +31 -0
  110. package/qtty-js/qtty-node/examples/arithmetic.mjs +64 -0
  111. package/qtty-js/qtty-node/examples/astronomy.mjs +90 -0
  112. package/qtty-js/qtty-node/examples/quickstart.mjs +36 -0
  113. package/qtty-js/qtty-node/examples/serialization.mjs +125 -0
  114. package/qtty-js/qtty-node/examples/unit_factories.mjs +74 -0
  115. package/qtty-js/qtty-node/index.d.ts +219 -0
  116. package/qtty-js/qtty-node/index.js +323 -0
  117. package/qtty-js/qtty-node/lib/DerivedQuantity.js +122 -0
  118. package/qtty-js/qtty-node/lib/Quantity.js +151 -0
  119. package/qtty-js/qtty-node/lib/backend.js +25 -0
  120. package/qtty-js/qtty-node/native.cjs +306 -0
  121. package/qtty-js/qtty-node/package-lock.json +3223 -0
  122. package/qtty-js/qtty-node/package.json +70 -0
  123. package/qtty-js/qtty-node/units.d.ts +299 -0
  124. package/qtty-js/qtty-node/units.js +210 -0
  125. package/qtty-js/qtty-web/Cargo.lock +767 -0
  126. package/qtty-js/qtty-web/Cargo.toml +21 -0
  127. package/qtty-js/qtty-web/index.d.ts +140 -0
  128. package/qtty-js/qtty-web/index.js +20 -0
  129. package/qtty-js/qtty-web/lib/DerivedQuantity.js +58 -0
  130. package/qtty-js/qtty-web/lib/Quantity.js +75 -0
  131. package/qtty-js/qtty-web/lib/backend.js +80 -0
  132. package/qtty-js/qtty-web/package.json +45 -0
  133. package/qtty-js/qtty-web/src/lib.rs +111 -0
  134. package/qtty-js/scripts/ci.sh +73 -0
  135. package/scripts/ci.sh +123 -0
  136. package/siderust-core/Cargo.lock +787 -0
  137. package/siderust-core/Cargo.toml +18 -0
  138. package/siderust-core/DEDUPLICATION.md +124 -0
  139. package/siderust-core/src/body.rs +120 -0
  140. package/siderust-core/src/events.rs +184 -0
  141. package/siderust-core/src/lib.rs +20 -0
  142. package/siderust-core/src/observer.rs +55 -0
  143. package/siderust-core/src/position.rs +213 -0
  144. package/siderust-node/.prettierignore +7 -0
  145. package/siderust-node/.prettierrc.json +6 -0
  146. package/siderust-node/Cargo.lock +906 -0
  147. package/siderust-node/Cargo.toml +29 -0
  148. package/siderust-node/README.md +109 -0
  149. package/siderust-node/__test__/index.test.mjs +248 -0
  150. package/siderust-node/build.rs +5 -0
  151. package/siderust-node/c8.config.json +3 -0
  152. package/siderust-node/eslint.config.js +31 -0
  153. package/siderust-node/examples/01_basic_coordinates.mjs +24 -0
  154. package/siderust-node/examples/02_coordinate_transformations.mjs +25 -0
  155. package/siderust-node/examples/03_all_frames_conversions.mjs +26 -0
  156. package/siderust-node/examples/04_all_center_conversions.mjs +24 -0
  157. package/siderust-node/examples/05_target_tracking.mjs +22 -0
  158. package/siderust-node/examples/06_night_events.mjs +18 -0
  159. package/siderust-node/examples/07_moon_properties.mjs +21 -0
  160. package/siderust-node/examples/08_solar_system.mjs +19 -0
  161. package/siderust-node/examples/09_star_observability.mjs +22 -0
  162. package/siderust-node/examples/10_time_periods.mjs +9 -0
  163. package/siderust-node/examples/11_serialization.mjs +31 -0
  164. package/siderust-node/examples/12_runtime_ephemeris.mjs +27 -0
  165. package/siderust-node/examples/13_coordinate_operations.mjs +20 -0
  166. package/siderust-node/index.d.ts +623 -0
  167. package/siderust-node/index.js +79 -0
  168. package/siderust-node/lib/Observer.js +112 -0
  169. package/siderust-node/lib/Star.js +118 -0
  170. package/siderust-node/lib/backend.js +63 -0
  171. package/siderust-node/lib/wrappers.js +566 -0
  172. package/siderust-node/main.js +20 -0
  173. package/siderust-node/native.cjs +360 -0
  174. package/siderust-node/package-lock.json +3261 -0
  175. package/siderust-node/package.json +71 -0
  176. package/siderust-node/src/body.rs +74 -0
  177. package/siderust-node/src/coordinates.rs +372 -0
  178. package/siderust-node/src/ephemeris.rs +462 -0
  179. package/siderust-node/src/events.rs +577 -0
  180. package/siderust-node/src/lib.rs +43 -0
  181. package/siderust-node/src/observer.rs +132 -0
  182. package/siderust-node/src/phase.rs +218 -0
  183. package/siderust-node/src/position.rs +292 -0
  184. package/siderust-node/src/star.rs +200 -0
  185. package/siderust-web/Cargo.lock +855 -0
  186. package/siderust-web/Cargo.toml +34 -0
  187. package/siderust-web/README.md +100 -0
  188. package/siderust-web/__test__/index.test.mjs +118 -0
  189. package/siderust-web/examples/github-pages/README.md +31 -0
  190. package/siderust-web/examples/github-pages/index.html +135 -0
  191. package/siderust-web/index.d.ts +311 -0
  192. package/siderust-web/index.js +66 -0
  193. package/siderust-web/lib/Observer.js +103 -0
  194. package/siderust-web/lib/Star.js +116 -0
  195. package/siderust-web/lib/backend.js +400 -0
  196. package/siderust-web/lib/wrappers.js +512 -0
  197. package/siderust-web/package.json +55 -0
  198. package/siderust-web/src/body.rs +69 -0
  199. package/siderust-web/src/coordinates.rs +302 -0
  200. package/siderust-web/src/ephemeris.rs +456 -0
  201. package/siderust-web/src/events.rs +520 -0
  202. package/siderust-web/src/lib.rs +51 -0
  203. package/siderust-web/src/observer.rs +117 -0
  204. package/siderust-web/src/phase.rs +190 -0
  205. package/siderust-web/src/position.rs +291 -0
  206. package/siderust-web/src/star.rs +178 -0
  207. package/tempoch-js/.github/workflows/ci.yml +142 -0
  208. package/tempoch-js/.gitmodules +3 -0
  209. package/tempoch-js/CHANGELOG.md +25 -0
  210. package/tempoch-js/LICENSE +661 -0
  211. package/tempoch-js/README.md +126 -0
  212. package/tempoch-js/package.json +20 -0
  213. package/tempoch-js/scripts/ci.sh +73 -0
  214. package/tempoch-js/tempoch/.github/workflows/ci.yml +113 -0
  215. package/tempoch-js/tempoch/CHANGELOG.md +82 -0
  216. package/tempoch-js/tempoch/Cargo.lock +947 -0
  217. package/tempoch-js/tempoch/Cargo.toml +3 -0
  218. package/tempoch-js/tempoch/LICENSE +661 -0
  219. package/tempoch-js/tempoch/README.md +76 -0
  220. package/tempoch-js/tempoch/tempoch/Cargo.toml +27 -0
  221. package/tempoch-js/tempoch/tempoch/examples/periods.rs +45 -0
  222. package/tempoch-js/tempoch/tempoch/examples/quickstart.rs +13 -0
  223. package/tempoch-js/tempoch/tempoch/src/lib.rs +49 -0
  224. package/tempoch-js/tempoch/tempoch/tests/integration.rs +57 -0
  225. package/tempoch-js/tempoch/tempoch-core/Cargo.toml +24 -0
  226. package/tempoch-js/tempoch/tempoch-core/src/delta_t.rs +345 -0
  227. package/tempoch-js/tempoch/tempoch-core/src/instant.rs +811 -0
  228. package/tempoch-js/tempoch/tempoch-core/src/julian_date_ext.rs +142 -0
  229. package/tempoch-js/tempoch/tempoch-core/src/lib.rs +81 -0
  230. package/tempoch-js/tempoch/tempoch-core/src/period.rs +1168 -0
  231. package/tempoch-js/tempoch/tempoch-core/src/scales.rs +779 -0
  232. package/tempoch-js/tempoch/tempoch-ffi/Cargo.lock +889 -0
  233. package/tempoch-js/tempoch/tempoch-ffi/Cargo.toml +26 -0
  234. package/tempoch-js/tempoch/tempoch-ffi/build.rs +24 -0
  235. package/tempoch-js/tempoch/tempoch-ffi/cbindgen.toml +30 -0
  236. package/tempoch-js/tempoch/tempoch-ffi/src/error.rs +19 -0
  237. package/tempoch-js/tempoch/tempoch-ffi/src/lib.rs +82 -0
  238. package/tempoch-js/tempoch/tempoch-ffi/src/period.rs +101 -0
  239. package/tempoch-js/tempoch/tempoch-ffi/src/time.rs +711 -0
  240. package/tempoch-js/tempoch/tempoch-ffi/tests/ffi.rs +265 -0
  241. package/tempoch-js/tempoch-node/.prettierignore +6 -0
  242. package/tempoch-js/tempoch-node/.prettierrc.json +6 -0
  243. package/tempoch-js/tempoch-node/Cargo.lock +496 -0
  244. package/tempoch-js/tempoch-node/Cargo.toml +29 -0
  245. package/tempoch-js/tempoch-node/README.md +265 -0
  246. package/tempoch-js/tempoch-node/__test__/index.test.mjs +598 -0
  247. package/tempoch-js/tempoch-node/build.rs +5 -0
  248. package/tempoch-js/tempoch-node/c8.config.json +3 -0
  249. package/tempoch-js/tempoch-node/eslint.config.js +31 -0
  250. package/tempoch-js/tempoch-node/examples/periods.mjs +79 -0
  251. package/tempoch-js/tempoch-node/examples/quickstart.mjs +71 -0
  252. package/tempoch-js/tempoch-node/examples/timescales.mjs +92 -0
  253. package/tempoch-js/tempoch-node/index.d.ts +280 -0
  254. package/tempoch-js/tempoch-node/index.js +32 -0
  255. package/tempoch-js/tempoch-node/lib/JulianDate.js +176 -0
  256. package/tempoch-js/tempoch-node/lib/ModifiedJulianDate.js +156 -0
  257. package/tempoch-js/tempoch-node/lib/Period.js +133 -0
  258. package/tempoch-js/tempoch-node/lib/backend.js +38 -0
  259. package/tempoch-js/tempoch-node/lib/qttyCompat.js +92 -0
  260. package/tempoch-js/tempoch-node/native.cjs +317 -0
  261. package/tempoch-js/tempoch-node/package-lock.json +3223 -0
  262. package/tempoch-js/tempoch-node/package.json +56 -0
  263. package/tempoch-js/tempoch-node/src/lib.rs +573 -0
  264. package/tempoch-js/tempoch-web/Cargo.toml +23 -0
  265. package/tempoch-js/tempoch-web/index.d.ts +95 -0
  266. package/tempoch-js/tempoch-web/index.js +27 -0
  267. package/tempoch-js/tempoch-web/lib/JulianDate.js +170 -0
  268. package/tempoch-js/tempoch-web/lib/ModifiedJulianDate.js +145 -0
  269. package/tempoch-js/tempoch-web/lib/Period.js +121 -0
  270. package/tempoch-js/tempoch-web/lib/backend.js +118 -0
  271. package/tempoch-js/tempoch-web/package.json +46 -0
  272. package/tempoch-js/tempoch-web/src/lib.rs +184 -0
@@ -0,0 +1,1270 @@
1
+ //! Length units.
2
+ //!
3
+ //! The canonical scaling unit for this dimension is [`Meter`] (`Meter::RATIO == 1.0`). All other
4
+ //! length units are expressed as exact or best‑available ratios to metres.
5
+ //!
6
+ //! This module provides:
7
+ //!
8
+ //! - **SI ladder**: the full metric prefix family for metres from yocto‑ to yotta‑.
9
+ //! - **Common defined units**: inch, foot, yard, (statute) mile, nautical mile, surveying units.
10
+ //! - **Astronomy**: astronomical unit (au), light‑year (ly), parsec (pc) and its multiples.
11
+ //! - **Geodesy and navigation**: Earth circumferences and related standards distances.
12
+ //! - **Fundamental physics lengths**: Bohr radius, Planck length, and related constants.
13
+ //! - **Nominal radii and distances**: available under the [`nominal`] submodule.
14
+ //!
15
+ //! Notes on definitions used here:
16
+ //!
17
+ //! - **Astronomical unit (au)** is **exactly** `149_597_870_700 m` (IAU 2012).
18
+ //! - **Parsec (pc)** is defined from au via `pc = au * 648000 / π` (exact, given au).
19
+ //! - **Light‑year (ly)** is derived from the exact speed of light `c = 299_792_458 m/s` and one
20
+ //! **Julian year** (`365.25 d`, `d = 86400 s`).
21
+ //! - **Imperial and surveying units** follow the current international definitions (e.g. the
22
+ //! international inch is exactly `0.0254 m`).
23
+ //! - **Nominal** astronomical/geodetic radii are grouped into [`nominal`] to avoid mixing them with
24
+ //! strictly defined units.
25
+ //!
26
+ //! This module aims to avoid avoidable precision loss by preferring rational expressions and exact
27
+ //! relationships over rounded convenience factors wherever practical.
28
+ //!
29
+ //! ```rust
30
+ //! use qtty_core::length::{AstronomicalUnits, Kilometer};
31
+ //!
32
+ //! let au = AstronomicalUnits::new(1.0);
33
+ //! let km = au.to::<Kilometer>();
34
+ //! assert_eq!(km.value(), 149_597_870.7);
35
+ //! ```
36
+ //!
37
+ //! ## All length units
38
+ //!
39
+ //! ```rust
40
+ //! use qtty_core::length::*;
41
+ //! use qtty_core::length::nominal::*;
42
+ //!
43
+ //! macro_rules! touch {
44
+ //! ($T:ty, $v:expr) => {{
45
+ //! let q = <$T>::new($v);
46
+ //! let _cloned = q;
47
+ //! assert!(q == q);
48
+ //! }};
49
+ //! }
50
+ //!
51
+ //! // SI sub-meter
52
+ //! touch!(Meters, 1.0); touch!(Decimeters, 1.0); touch!(Centimeters, 1.0);
53
+ //! touch!(Millimeters, 1.0); touch!(Micrometers, 1.0); touch!(Nanometers, 1.0);
54
+ //! touch!(Picometers, 1.0); touch!(Femtometers, 1.0); touch!(Attometers, 1.0);
55
+ //! touch!(Zeptometers, 1.0); touch!(Yoctometers, 1.0);
56
+ //! // SI super-meter
57
+ //! touch!(Decameters, 1.0); touch!(Hectometers, 1.0); touch!(Kilometers, 1.0);
58
+ //! touch!(Megameters, 1.0); touch!(Gigameters, 1.0); touch!(Terameters, 1.0);
59
+ //! touch!(Petameters, 1.0); touch!(Exameters, 1.0); touch!(Zettameters, 1.0);
60
+ //! touch!(Yottameters, 1.0);
61
+ //! // Astronomical
62
+ //! touch!(AstronomicalUnits, 1.0); touch!(LightYears, 1.0); touch!(Parsecs, 1.0);
63
+ //! touch!(Kiloparsecs, 1.0); touch!(Megaparsecs, 1.0); touch!(Gigaparsecs, 1.0);
64
+ //! // Imperial
65
+ //! touch!(Inches, 1.0); touch!(Feet, 1.0); touch!(Yards, 1.0);
66
+ //! touch!(Miles, 1.0); touch!(NauticalMiles, 1.0); touch!(Chains, 1.0);
67
+ //! touch!(Rods, 1.0); touch!(Links, 1.0); touch!(Fathoms, 1.0);
68
+ //! // Geodesy
69
+ //! touch!(EarthMeridionalCircumferences, 1.0);
70
+ //! touch!(EarthEquatorialCircumferences, 1.0);
71
+ //! // Physics
72
+ //! touch!(BohrRadii, 1.0); touch!(ClassicalElectronRadii, 1.0);
73
+ //! touch!(PlanckLengths, 1.0); touch!(ElectronReducedComptonWavelengths, 1.0);
74
+ //! // Nominal
75
+ //! touch!(SolarRadiuses, 1.0); touch!(EarthRadii, 1.0);
76
+ //! touch!(EarthEquatorialRadii, 1.0); touch!(EarthPolarRadii, 1.0);
77
+ //! touch!(LunarRadii, 1.0); touch!(JupiterRadii, 1.0);
78
+ //! touch!(LunarDistances, 1.0); touch!(SolarDiameters, 1.0);
79
+ //! ```
80
+
81
+ use crate::{Quantity, Unit};
82
+ use core::f64::consts::PI;
83
+ use qtty_derive::Unit;
84
+
85
+ /// Re-export from the dimension module.
86
+ pub use crate::dimension::Length;
87
+
88
+ /// Marker trait for any [`Unit`] whose dimension is [`Length`].
89
+ pub trait LengthUnit: Unit<Dim = Length> {}
90
+ impl<T: Unit<Dim = Length>> LengthUnit for T {}
91
+
92
+ // ─────────────────────────────────────────────────────────────────────────────
93
+ // SI base unit and core helpers
94
+ // ─────────────────────────────────────────────────────────────────────────────
95
+
96
+ /// Metre (SI base unit).
97
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
98
+ #[unit(symbol = "m", dimension = Length, ratio = 1.0)]
99
+ pub struct Meter;
100
+ /// A quantity measured in metres.
101
+ pub type Meters = Quantity<Meter>;
102
+ /// One metre.
103
+ pub const M: Meters = Meters::new(1.0);
104
+
105
+ /// Kilometre (`1000 m`).
106
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
107
+ #[unit(symbol = "km", dimension = Length, ratio = 1_000.0)]
108
+ pub struct Kilometer;
109
+ /// Type alias shorthand for [`Kilometer`].
110
+ pub type Km = Kilometer;
111
+ /// A quantity measured in kilometres.
112
+ pub type Kilometers = Quantity<Km>;
113
+ /// One kilometre.
114
+ pub const KM: Kilometers = Kilometers::new(1.0);
115
+
116
+ /// Centimetre (`1e-2 m`).
117
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
118
+ #[unit(symbol = "cm", dimension = Length, ratio = 1e-2)]
119
+ pub struct Centimeter;
120
+ /// Type alias shorthand for [`Centimeter`].
121
+ pub type Cm = Centimeter;
122
+ /// A quantity measured in centimetres.
123
+ pub type Centimeters = Quantity<Cm>;
124
+ /// One centimetre.
125
+ pub const CM: Centimeters = Centimeters::new(1.0);
126
+
127
+ /// Millimetre (`1e-3 m`).
128
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
129
+ #[unit(symbol = "mm", dimension = Length, ratio = 1e-3)]
130
+ pub struct Millimeter;
131
+ /// Type alias shorthand for [`Millimeter`].
132
+ pub type Mm = Millimeter;
133
+ /// A quantity measured in millimetres.
134
+ pub type Millimeters = Quantity<Mm>;
135
+ /// One millimetre.
136
+ pub const MM: Millimeters = Millimeters::new(1.0);
137
+
138
+ /// Micrometre (`1e-6 m`).
139
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
140
+ #[unit(symbol = "μm", dimension = Length, ratio = 1e-6)]
141
+ pub struct Micrometer;
142
+ /// Type alias shorthand for [`Micrometer`].
143
+ pub type Um = Micrometer;
144
+ /// A quantity measured in micrometres.
145
+ pub type Micrometers = Quantity<Um>;
146
+ /// One micrometre.
147
+ pub const UM: Micrometers = Micrometers::new(1.0);
148
+
149
+ /// Nanometre (`1e-9 m`).
150
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
151
+ #[unit(symbol = "nm", dimension = Length, ratio = 1e-9)]
152
+ pub struct Nanometer;
153
+ /// Type alias shorthand for [`Nanometer`].
154
+ pub type Nm = Nanometer;
155
+ /// A quantity measured in nanometres.
156
+ pub type Nanometers = Quantity<Nm>;
157
+ /// One nanometre.
158
+ pub const NM: Nanometers = Nanometers::new(1.0);
159
+
160
+ /// Picometre (`1e-12 m`).
161
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
162
+ #[unit(symbol = "pm", dimension = Length, ratio = 1e-12)]
163
+ pub struct Picometer;
164
+ /// A quantity measured in picometres.
165
+ pub type Picometers = Quantity<Picometer>;
166
+ /// One picometre.
167
+ pub const PMETER: Picometers = Picometers::new(1.0);
168
+
169
+ /// Femtometre (`1e-15 m`).
170
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
171
+ #[unit(symbol = "fm", dimension = Length, ratio = 1e-15)]
172
+ pub struct Femtometer;
173
+ /// A quantity measured in femtometres.
174
+ pub type Femtometers = Quantity<Femtometer>;
175
+ /// One femtometre.
176
+ pub const FM: Femtometers = Femtometers::new(1.0);
177
+
178
+ /// Attometre (`1e-18 m`).
179
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
180
+ #[unit(symbol = "am", dimension = Length, ratio = 1e-18)]
181
+ pub struct Attometer;
182
+ /// A quantity measured in attometres.
183
+ pub type Attometers = Quantity<Attometer>;
184
+ /// One attometre.
185
+ pub const AM: Attometers = Attometers::new(1.0);
186
+
187
+ /// Zeptometre (`1e-21 m`).
188
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
189
+ #[unit(symbol = "zm", dimension = Length, ratio = 1e-21)]
190
+ pub struct Zeptometer;
191
+ /// A quantity measured in zeptometres.
192
+ pub type Zeptometers = Quantity<Zeptometer>;
193
+ /// One zeptometre.
194
+ pub const ZMETER: Zeptometers = Zeptometers::new(1.0);
195
+
196
+ /// Yoctometre (`1e-24 m`).
197
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
198
+ #[unit(symbol = "ym", dimension = Length, ratio = 1e-24)]
199
+ pub struct Yoctometer;
200
+ /// A quantity measured in yoctometres.
201
+ pub type Yoctometers = Quantity<Yoctometer>;
202
+ /// One yoctometre.
203
+ pub const YMETER: Yoctometers = Yoctometers::new(1.0);
204
+
205
+ /// Megametre (`1e6 m`).
206
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
207
+ #[unit(symbol = "Mm", dimension = Length, ratio = 1e6)]
208
+ pub struct Megameter;
209
+ /// Type alias shorthand for [`Megameter`].
210
+ pub type MegaMeter = Megameter;
211
+ /// A quantity measured in megametres.
212
+ pub type Megameters = Quantity<Megameter>;
213
+ /// One megametre.
214
+ pub const MEGAMETER: Megameters = Megameters::new(1.0);
215
+
216
+ /// Decimetre (`1e-1 m`).
217
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
218
+ #[unit(symbol = "dm", dimension = Length, ratio = 1e-1)]
219
+ pub struct Decimeter;
220
+ /// A quantity measured in decimetres.
221
+ pub type Decimeters = Quantity<Decimeter>;
222
+ /// One decimetre.
223
+ pub const DM: Decimeters = Decimeters::new(1.0);
224
+
225
+ /// Decametre (`1e1 m`).
226
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
227
+ #[unit(symbol = "dam", dimension = Length, ratio = 1e1)]
228
+ pub struct Decameter;
229
+ /// A quantity measured in decametres.
230
+ pub type Decameters = Quantity<Decameter>;
231
+ /// One decametre.
232
+ pub const DAM: Decameters = Decameters::new(1.0);
233
+
234
+ /// Hectometre (`1e2 m`).
235
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
236
+ #[unit(symbol = "hm", dimension = Length, ratio = 1e2)]
237
+ pub struct Hectometer;
238
+ /// A quantity measured in hectometres.
239
+ pub type Hectometers = Quantity<Hectometer>;
240
+ /// One hectometre.
241
+ pub const HM: Hectometers = Hectometers::new(1.0);
242
+
243
+ /// Gigametre (`1e9 m`).
244
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
245
+ #[unit(symbol = "Gm", dimension = Length, ratio = 1e9)]
246
+ pub struct Gigameter;
247
+ /// A quantity measured in gigametres.
248
+ pub type Gigameters = Quantity<Gigameter>;
249
+ /// One gigametre.
250
+ pub const GM: Gigameters = Gigameters::new(1.0);
251
+
252
+ /// Terametre (`1e12 m`).
253
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
254
+ #[unit(symbol = "Tm", dimension = Length, ratio = 1e12)]
255
+ pub struct Terameter;
256
+ /// A quantity measured in terametres.
257
+ pub type Terameters = Quantity<Terameter>;
258
+ /// One terametre.
259
+ pub const TM: Terameters = Terameters::new(1.0);
260
+
261
+ /// Petametre (`1e15 m`).
262
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
263
+ #[unit(symbol = "Pm", dimension = Length, ratio = 1e15)]
264
+ pub struct Petameter;
265
+ /// A quantity measured in petametres.
266
+ pub type Petameters = Quantity<Petameter>;
267
+ /// One petametre.
268
+ pub const PM: Petameters = Petameters::new(1.0);
269
+
270
+ /// Exametre (`1e18 m`).
271
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
272
+ #[unit(symbol = "Em", dimension = Length, ratio = 1e18)]
273
+ pub struct Exameter;
274
+ /// A quantity measured in exametres.
275
+ pub type Exameters = Quantity<Exameter>;
276
+ /// One exametre.
277
+ pub const EM: Exameters = Exameters::new(1.0);
278
+
279
+ /// Zettametre (`1e21 m`).
280
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
281
+ #[unit(symbol = "Zm", dimension = Length, ratio = 1e21)]
282
+ pub struct Zettameter;
283
+ /// A quantity measured in zettametres.
284
+ pub type Zettameters = Quantity<Zettameter>;
285
+ /// One zettametre.
286
+ pub const ZM: Zettameters = Zettameters::new(1.0);
287
+
288
+ /// Yottametre (`1e24 m`).
289
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
290
+ #[unit(symbol = "Ym", dimension = Length, ratio = 1e24)]
291
+ pub struct Yottameter;
292
+ /// A quantity measured in yottametres.
293
+ pub type Yottameters = Quantity<Yottameter>;
294
+ /// One yottametre.
295
+ pub const YM: Yottameters = Yottameters::new(1.0);
296
+
297
+ // ─────────────────────────────────────────────────────────────────────────────
298
+ // Astronomical distance units
299
+ // ─────────────────────────────────────────────────────────────────────────────
300
+
301
+ /// Astronomical unit (au). Exact (IAU 2012): metres per au.
302
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
303
+ #[unit(symbol = "au", dimension = Length, ratio = 149_597_870_700.0)]
304
+ pub struct AstronomicalUnit;
305
+ /// Type alias shorthand for [`AstronomicalUnit`].
306
+ pub type Au = AstronomicalUnit;
307
+ /// A quantity measured in astronomical units.
308
+ pub type AstronomicalUnits = Quantity<Au>;
309
+ /// One astronomical unit.
310
+ pub const AU: AstronomicalUnits = AstronomicalUnits::new(1.0);
311
+
312
+ // Exact speed of light and Julian year, used to derive the light‑year ratio.
313
+ const SPEED_OF_LIGHT_M_PER_S: f64 = 299_792_458.0;
314
+ const SECONDS_PER_DAY: f64 = 86_400.0;
315
+ const DAYS_PER_JULIAN_YEAR: f64 = 36525.0 / 100.0; // 365.25 d
316
+ const SECONDS_PER_JULIAN_YEAR: f64 = SECONDS_PER_DAY * DAYS_PER_JULIAN_YEAR;
317
+ const METERS_PER_LIGHT_YEAR: f64 = SPEED_OF_LIGHT_M_PER_S * SECONDS_PER_JULIAN_YEAR;
318
+
319
+ /// Light-year (ly): distance light travels in one Julian year (`365.25 d`) at `c = 299_792_458 m/s`.
320
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
321
+ #[unit(symbol = "ly", dimension = Length, ratio = METERS_PER_LIGHT_YEAR)]
322
+ pub struct LightYear;
323
+ /// Type alias shorthand for [`LightYear`].
324
+ pub type Ly = LightYear;
325
+ /// A quantity measured in light-years.
326
+ pub type LightYears = Quantity<Ly>;
327
+ /// One light-year.
328
+ pub const LY: LightYears = LightYears::new(1.0);
329
+
330
+ /// Parsec (pc): `pc = au * 648000 / π` (exact given au).
331
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
332
+ #[unit(symbol = "pc", dimension = Length, ratio = 149_597_870_700.0 * (648_000.0 / PI))]
333
+ pub struct Parsec;
334
+ /// Type alias shorthand for [`Parsec`].
335
+ pub type Pc = Parsec;
336
+ /// A quantity measured in parsecs.
337
+ pub type Parsecs = Quantity<Pc>;
338
+ /// One parsec.
339
+ pub const PC: Parsecs = Parsecs::new(1.0);
340
+
341
+ /// Kiloparsec (kpc): `1e3 pc`.
342
+ #[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))]
344
+ pub struct Kiloparsec;
345
+ /// A quantity measured in kiloparsecs.
346
+ pub type Kiloparsecs = Quantity<Kiloparsec>;
347
+ /// One kiloparsec.
348
+ pub const KPC: Kiloparsecs = Kiloparsecs::new(1.0);
349
+
350
+ /// Megaparsec (Mpc): `1e6 pc`.
351
+ #[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))]
353
+ pub struct Megaparsec;
354
+ /// A quantity measured in megaparsecs.
355
+ pub type Megaparsecs = Quantity<Megaparsec>;
356
+ /// One megaparsec.
357
+ pub const MPC: Megaparsecs = Megaparsecs::new(1.0);
358
+
359
+ /// Gigaparsec (Gpc): `1e9 pc`.
360
+ #[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))]
362
+ pub struct Gigaparsec;
363
+ /// A quantity measured in gigaparsecs.
364
+ pub type Gigaparsecs = Quantity<Gigaparsec>;
365
+ /// One gigaparsec.
366
+ pub const GPC: Gigaparsecs = Gigaparsecs::new(1.0);
367
+
368
+ // ─────────────────────────────────────────────────────────────────────────────
369
+ // Imperial, US customary, and surveying units
370
+ // ─────────────────────────────────────────────────────────────────────────────
371
+
372
+ /// Inch (`0.0254 m` exactly).
373
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
374
+ #[unit(symbol = "in", dimension = Length, ratio = 254.0 / 10_000.0)]
375
+ pub struct Inch;
376
+ /// A quantity measured in inches.
377
+ pub type Inches = Quantity<Inch>;
378
+ /// One inch.
379
+ pub const INCH: Inches = Inches::new(1.0);
380
+
381
+ /// Foot (`0.3048 m` exactly).
382
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
383
+ #[unit(symbol = "ft", dimension = Length, ratio = 3048.0 / 10_000.0)]
384
+ pub struct Foot;
385
+ /// A quantity measured in feet.
386
+ pub type Feet = Quantity<Foot>;
387
+ /// One foot.
388
+ pub const FT: Feet = Feet::new(1.0);
389
+
390
+ /// Yard (`0.9144 m` exactly).
391
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
392
+ #[unit(symbol = "yd", dimension = Length, ratio = 9144.0 / 10_000.0)]
393
+ pub struct Yard;
394
+ /// A quantity measured in yards.
395
+ pub type Yards = Quantity<Yard>;
396
+ /// One yard.
397
+ pub const YD: Yards = Yards::new(1.0);
398
+
399
+ /// (Statute) mile (`1609.344 m` exactly).
400
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
401
+ #[unit(symbol = "mi", dimension = Length, ratio = 1_609_344.0 / 1_000.0)]
402
+ pub struct Mile;
403
+ /// A quantity measured in miles.
404
+ pub type Miles = Quantity<Mile>;
405
+ /// One mile.
406
+ pub const MI: Miles = Miles::new(1.0);
407
+
408
+ /// Nautical mile (`1852 m` exactly).
409
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
410
+ #[unit(symbol = "nmi", dimension = Length, ratio = 1_852.0)]
411
+ pub struct NauticalMile;
412
+ /// A quantity measured in nautical miles.
413
+ pub type NauticalMiles = Quantity<NauticalMile>;
414
+ /// One nautical mile.
415
+ pub const NMI: NauticalMiles = NauticalMiles::new(1.0);
416
+
417
+ /// Chain (`66 ft` exactly).
418
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
419
+ #[unit(symbol = "ch", dimension = Length, ratio = 66.0 * (3048.0 / 10_000.0))]
420
+ pub struct Chain;
421
+ /// A quantity measured in chains.
422
+ pub type Chains = Quantity<Chain>;
423
+ /// One chain.
424
+ pub const CHAIN: Chains = Chains::new(1.0);
425
+
426
+ /// Rod / pole / perch (`16.5 ft` exactly).
427
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
428
+ #[unit(symbol = "rd", dimension = Length, ratio = 16.5 * (3048.0 / 10_000.0))]
429
+ pub struct Rod;
430
+ /// A quantity measured in rods/poles/perches.
431
+ pub type Rods = Quantity<Rod>;
432
+ /// One rod.
433
+ pub const ROD: Rods = Rods::new(1.0);
434
+
435
+ /// Link (`1/100 of a chain`, i.e. `0.66 ft`).
436
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
437
+ #[unit(symbol = "lk", dimension = Length, ratio = (66.0 / 100.0) * (3048.0 / 10_000.0))]
438
+ pub struct Link;
439
+ /// A quantity measured in links.
440
+ pub type Links = Quantity<Link>;
441
+ /// One link.
442
+ pub const LINK: Links = Links::new(1.0);
443
+
444
+ /// Fathom (`6 ft` exactly).
445
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
446
+ #[unit(symbol = "ftm", dimension = Length, ratio = 6.0 * (3048.0 / 10_000.0))]
447
+ pub struct Fathom;
448
+ /// A quantity measured in fathoms.
449
+ pub type Fathoms = Quantity<Fathom>;
450
+ /// One fathom.
451
+ pub const FTM: Fathoms = Fathoms::new(1.0);
452
+
453
+ // ─────────────────────────────────────────────────────────────────────────────
454
+ // Geodesy and navigation
455
+ // ─────────────────────────────────────────────────────────────────────────────
456
+
457
+ /// Earth meridional circumference (approximate mean value).
458
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
459
+ #[unit(symbol = "Cmer", dimension = Length, ratio = 40_007_863.0)]
460
+ pub struct EarthMeridionalCircumference;
461
+ /// A quantity measured in Earth meridional circumferences.
462
+ pub type EarthMeridionalCircumferences = Quantity<EarthMeridionalCircumference>;
463
+ /// One Earth meridional circumference.
464
+ pub const C_MERIDIONAL: EarthMeridionalCircumferences = EarthMeridionalCircumferences::new(1.0);
465
+
466
+ /// Earth equatorial circumference.
467
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
468
+ #[unit(symbol = "Ceq", dimension = Length, ratio = 40_075_017.0)]
469
+ pub struct EarthEquatorialCircumference;
470
+ /// A quantity measured in Earth equatorial circumferences.
471
+ pub type EarthEquatorialCircumferences = Quantity<EarthEquatorialCircumference>;
472
+ /// One Earth equatorial circumference.
473
+ pub const C_EQUATORIAL: EarthEquatorialCircumferences = EarthEquatorialCircumferences::new(1.0);
474
+
475
+ // ─────────────────────────────────────────────────────────────────────────────
476
+ // Fundamental physics lengths (CODATA values)
477
+ // ─────────────────────────────────────────────────────────────────────────────
478
+
479
+ /// Bohr radius (`a0`). CODATA 2018 value in metres.
480
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
481
+ #[unit(symbol = "a0", dimension = Length, ratio = 5.291_772_109_03e-11)]
482
+ pub struct BohrRadius;
483
+ /// A quantity measured in Bohr radii.
484
+ pub type BohrRadii = Quantity<BohrRadius>;
485
+ /// One Bohr radius.
486
+ pub const A0: BohrRadii = BohrRadii::new(1.0);
487
+
488
+ /// Classical electron radius (`re`). CODATA 2018 value in metres.
489
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
490
+ #[unit(symbol = "re", dimension = Length, ratio = 2.817_940_326_2e-15)]
491
+ pub struct ClassicalElectronRadius;
492
+ /// A quantity measured in classical electron radii.
493
+ pub type ClassicalElectronRadii = Quantity<ClassicalElectronRadius>;
494
+ /// One classical electron radius.
495
+ pub const RE: ClassicalElectronRadii = ClassicalElectronRadii::new(1.0);
496
+
497
+ /// Planck length (`lp`). CODATA 2018 value in metres.
498
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
499
+ #[unit(symbol = "lp", dimension = Length, ratio = 1.616_255e-35)]
500
+ pub struct PlanckLength;
501
+ /// A quantity measured in Planck lengths.
502
+ pub type PlanckLengths = Quantity<PlanckLength>;
503
+ /// One Planck length.
504
+ pub const LP: PlanckLengths = PlanckLengths::new(1.0);
505
+
506
+ /// Reduced Compton wavelength of the electron (`lambda_bar_e`). CODATA 2018 value in metres.
507
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
508
+ #[unit(symbol = "lambda_bar_e", dimension = Length, ratio = 3.861_592_679_6e-13)]
509
+ pub struct ElectronReducedComptonWavelength;
510
+ /// A quantity measured in reduced Compton wavelengths of the electron.
511
+ pub type ElectronReducedComptonWavelengths = Quantity<ElectronReducedComptonWavelength>;
512
+ /// One reduced Compton wavelength of the electron.
513
+ pub const LAMBDA_BAR_E: ElectronReducedComptonWavelengths =
514
+ ElectronReducedComptonWavelengths::new(1.0);
515
+
516
+ // ─────────────────────────────────────────────────────────────────────────────
517
+ // Nominal radii and distances
518
+ // ─────────────────────────────────────────────────────────────────────────────
519
+
520
+ /// Nominal astronomical and planetary radii and related distances.
521
+ ///
522
+ /// Values in this module are **nominal** (conventionally rounded) and are kept separate from the
523
+ /// main length namespace to avoid confusion with strictly defined units.
524
+ pub mod nominal {
525
+ use super::*;
526
+
527
+ /// Solar radius (R☉). Nominal value: metres per R☉.
528
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
529
+ #[unit(symbol = "Rsun", dimension = Length, ratio = 695_700_000.0)]
530
+ pub struct SolarRadius;
531
+ /// A quantity measured in solar radii.
532
+ pub type SolarRadiuses = Quantity<SolarRadius>;
533
+ /// One solar radius.
534
+ pub const RSUN: SolarRadiuses = SolarRadiuses::new(1.0);
535
+
536
+ /// Earth mean radius (nominal).
537
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
538
+ #[unit(symbol = "Rearth", dimension = Length, ratio = 6_371_000.0)]
539
+ pub struct EarthRadius;
540
+ /// A quantity measured in Earth radii.
541
+ pub type EarthRadii = Quantity<EarthRadius>;
542
+ /// One Earth radius (mean).
543
+ pub const R_EARTH: EarthRadii = EarthRadii::new(1.0);
544
+
545
+ /// Earth equatorial radius (WGS84).
546
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
547
+ #[unit(symbol = "Rearth_eq", dimension = Length, ratio = 6_378_137.0)]
548
+ pub struct EarthEquatorialRadius;
549
+ /// A quantity measured in Earth equatorial radii.
550
+ pub type EarthEquatorialRadii = Quantity<EarthEquatorialRadius>;
551
+ /// One Earth equatorial radius.
552
+ pub const R_EARTH_EQ: EarthEquatorialRadii = EarthEquatorialRadii::new(1.0);
553
+
554
+ /// Earth polar radius.
555
+ #[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
+ /// A quantity measured in Earth polar radii.
559
+ pub type EarthPolarRadii = Quantity<EarthPolarRadius>;
560
+ /// One Earth polar radius.
561
+ pub const R_EARTH_P: EarthPolarRadii = EarthPolarRadii::new(1.0);
562
+
563
+ /// Lunar radius (mean, nominal).
564
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
565
+ #[unit(symbol = "Rmoon", dimension = Length, ratio = 1_737_400.0)]
566
+ pub struct LunarRadius;
567
+ /// A quantity measured in lunar radii.
568
+ pub type LunarRadii = Quantity<LunarRadius>;
569
+ /// One lunar radius.
570
+ pub const R_MOON: LunarRadii = LunarRadii::new(1.0);
571
+
572
+ /// Jupiter equatorial radius (nominal).
573
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
574
+ #[unit(symbol = "Rjup", dimension = Length, ratio = 71_492_000.0)]
575
+ pub struct JupiterRadius;
576
+ /// A quantity measured in Jupiter radii.
577
+ pub type JupiterRadii = Quantity<JupiterRadius>;
578
+ /// One Jupiter radius.
579
+ pub const R_JUPITER: JupiterRadii = JupiterRadii::new(1.0);
580
+
581
+ /// Lunar distance (Earth–Moon mean distance, LD).
582
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
583
+ #[unit(symbol = "LD", dimension = Length, ratio = 384_400_000.0)]
584
+ pub struct LunarDistance;
585
+ /// A quantity measured in lunar distances.
586
+ pub type LunarDistances = Quantity<LunarDistance>;
587
+ /// One lunar distance.
588
+ pub const LD: LunarDistances = LunarDistances::new(1.0);
589
+
590
+ /// Solar diameter (twice the solar radius).
591
+ #[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
+ /// A quantity measured in solar diameters.
595
+ pub type SolarDiameters = Quantity<SolarDiameter>;
596
+ /// One solar diameter.
597
+ pub const D_SUN: SolarDiameters = SolarDiameters::new(1.0);
598
+
599
+ // Allow convenient conversions between selected nominal units and core
600
+ // length units (e.g., SolarRadius <-> Kilometer) without polluting the
601
+ // main length namespace with nominal types.
602
+ crate::impl_unit_from_conversions!(SolarRadius, Kilometer);
603
+ #[cfg(feature = "cross-unit-ops")]
604
+ crate::impl_unit_cross_unit_ops!(SolarRadius, Kilometer);
605
+ }
606
+
607
+ // Generate all bidirectional From implementations between length units.
608
+ //
609
+ // This single invocation ensures that any quantity measured in one length unit can be
610
+ // converted into any other via `From`/`Into`, mirroring the previous behavior while
611
+ // including the extended unit set.
612
+ crate::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
+ // Optional cross-unit operator support (`==`, `<`, etc.).
658
+ #[cfg(feature = "cross-unit-ops")]
659
+ crate::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)]
705
+ mod 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
+ // ─────────────────────────────────────────────────────────────────────────────
712
+ // Basic conversions
713
+ // ─────────────────────────────────────────────────────────────────────────────
714
+
715
+ #[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
+ // 1 AU = 149,597,870,700 meters (exact, IAU 2012).
734
+ 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
+ // 1 AU = 149,597,870,700 m => 149,597,870.7 km.
742
+ 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
+ // 1 LY = c * 365.25 d, where d = 86400 s
750
+ 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
+ // 1 LY ≈ 9.461e12 km
758
+ assert_relative_eq!(km.value(), 9_460_730_472_580.000_8, max_relative = 1e-9);
759
+ }
760
+
761
+ // ─────────────────────────────────────────────────────────────────────────────
762
+ // AU <-> LY conversions
763
+ // ─────────────────────────────────────────────────────────────────────────────
764
+
765
+ #[test]
766
+ fn au_to_light_year() {
767
+ let au = AstronomicalUnits::new(1.0);
768
+ let ly = au.to::<LightYear>();
769
+ // 1 AU ≈ 1.582e-5 LY
770
+ 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
+ // 1 LY ≈ 63,241 AU
778
+ 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
+ // ─────────────────────────────────────────────────────────────────────────────
796
+ // Parsec conversions
797
+ // ─────────────────────────────────────────────────────────────────────────────
798
+
799
+ #[test]
800
+ fn parsec_to_light_year() {
801
+ let pc = Parsecs::new(1.0);
802
+ let ly = pc.to::<LightYear>();
803
+ // 1 pc expressed in light-years, using the exact AU-based definition.
804
+ 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
+ // 1 pc ≈ 206,265 AU (using exact definition: 1 pc = 3.26 LY, 1 LY ≈ 63241 AU)
813
+ // So 1 pc ≈ 3.26 * 63241 ≈ 206,165 AU
814
+ assert_relative_eq!(au.value(), 3.26 * 63241.0, max_relative = 1e-2);
815
+ }
816
+
817
+ #[test]
818
+ fn parsec_ratio_sanity() {
819
+ // Parsec is defined from AU: pc = au * 648000 / π
820
+ 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
+ // ─────────────────────────────────────────────────────────────────────────────
826
+ // Solar radius
827
+ // ─────────────────────────────────────────────────────────────────────────────
828
+
829
+ #[test]
830
+ fn solar_radius_to_meters() {
831
+ let sr = SolarRadiuses::new(1.0);
832
+ let m = sr.to::<Meter>();
833
+ // 1 R☉ = 695,700 km = 695,700,000 m
834
+ 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
+ // 1 R☉ = 695,700 km
842
+ assert_abs_diff_eq!(km.value(), 695_700.0, epsilon = 1e-6);
843
+ }
844
+
845
+ // ─────────────────────────────────────────────────────────────────────────────
846
+ // Roundtrip conversions
847
+ // ─────────────────────────────────────────────────────────────────────────────
848
+
849
+ #[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
+ // ─────────────────────────────────────────────────────────────────────────
874
+ // Exact relationship tests for new units
875
+ // ─────────────────────────────────────────────────────────────────────────
876
+
877
+ #[test]
878
+ fn inch_to_meter_exact_ratio() {
879
+ let inch = Inches::new(1.0);
880
+ let m = inch.to::<Meter>();
881
+ // International inch: exactly 0.0254 m
882
+ 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
+ // International nautical mile: exactly 1852 m
890
+ assert_abs_diff_eq!(m.value(), 1852.0, epsilon = 1e-12);
891
+ }
892
+
893
+ // ─────────────────────────────────────────────────────────────────────────
894
+ // Roundtrip sanity for representative units
895
+ // ─────────────────────────────────────────────────────────────────────────
896
+
897
+ #[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
+ // ─────────────────────────────────────────────────────────────────────────────
922
+ // Property-based tests
923
+ // ─────────────────────────────────────────────────────────────────────────────
924
+
925
+ 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
+ // 1 km = 1000 m
939
+ 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
+ // ─────────────────────────────────────────────────────────────────────────
961
+ // SI sub-meter ladder
962
+ // ─────────────────────────────────────────────────────────────────────────
963
+
964
+ #[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
+ // ─────────────────────────────────────────────────────────────────────────
1025
+ // SI super-meter ladder
1026
+ // ─────────────────────────────────────────────────────────────────────────
1027
+
1028
+ #[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
+ // ─────────────────────────────────────────────────────────────────────────
1083
+ // Imperial / surveying units
1084
+ // ─────────────────────────────────────────────────────────────────────────
1085
+
1086
+ #[test]
1087
+ fn foot_to_meter() {
1088
+ let q = Feet::new(1.0);
1089
+ // 1 ft = 0.3048 m exactly
1090
+ 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
+ // 1 yd = 0.9144 m exactly
1097
+ 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
+ // 1 mi = 1609.344 m exactly
1104
+ 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
+ // 1 fathom = 6 ft
1111
+ 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
+ // 1 chain = 66 ft
1118
+ 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
+ // 1 rod = 16.5 ft
1125
+ 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
+ // 100 links = 1 chain = 66 ft
1132
+ assert_relative_eq!(q.to::<Foot>().value(), 66.0, max_relative = 1e-14);
1133
+ }
1134
+
1135
+ // ─────────────────────────────────────────────────────────────────────────
1136
+ // Larger astronomical parsec multiples
1137
+ // ─────────────────────────────────────────────────────────────────────────
1138
+
1139
+ #[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
+ // ─────────────────────────────────────────────────────────────────────────
1152
+ // Geodesy
1153
+ // ─────────────────────────────────────────────────────────────────────────
1154
+
1155
+ #[test]
1156
+ fn earth_meridional_circumference_to_km() {
1157
+ let q = EarthMeridionalCircumferences::new(1.0);
1158
+ // ≈ 40_007.863 km
1159
+ 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
+ // ≈ 40_075.017 km
1166
+ assert_relative_eq!(q.to::<Kilometer>().value(), 40_075.017, max_relative = 1e-6);
1167
+ }
1168
+
1169
+ // ─────────────────────────────────────────────────────────────────────────
1170
+ // Physics lengths
1171
+ // ─────────────────────────────────────────────────────────────────────────
1172
+
1173
+ #[test]
1174
+ fn bohr_radius_to_picometers() {
1175
+ let q = BohrRadii::new(1.0);
1176
+ // a0 ≈ 52.9177 pm
1177
+ 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
+ // re ≈ 2.81794 fm
1184
+ 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
+ // Just check ratio round-trips without numeric overflow
1194
+ 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
+ // λ̄_e ≈ 386.159 fm
1203
+ assert_relative_eq!(
1204
+ q.to::<Femtometer>().value(),
1205
+ 386.159_267_96,
1206
+ max_relative = 1e-7
1207
+ );
1208
+ }
1209
+
1210
+ // ─────────────────────────────────────────────────────────────────────────
1211
+ // Nominal submodule
1212
+ // ─────────────────────────────────────────────────────────────────────────
1213
+
1214
+ #[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
+ }