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,488 @@
1
+ //! Mass units.
2
+ //!
3
+ //! The canonical scaling unit for this dimension is [`Gram`] (`Gram::RATIO == 1.0`).
4
+ //!
5
+ //! This module aims for practical completeness while avoiding avoidable precision loss:
6
+ //! - **SI grams**: full prefix ladder (yocto … yotta).
7
+ //! - **Defined non-SI**: tonne, avoirdupois units, carat, grain.
8
+ //! - **Science/astro**: atomic mass unit (u/Da), nominal solar mass.
9
+ //!
10
+ //! ```rust
11
+ //! use qtty_core::mass::{Kilograms, SolarMass};
12
+ //!
13
+ //! let m = Kilograms::new(1.0);
14
+ //! let sm = m.to::<SolarMass>();
15
+ //! assert!(sm.value() < 1.0);
16
+ //! ```
17
+ //!
18
+ //! ## All mass units
19
+ //!
20
+ //! ```rust
21
+ //! use qtty_core::mass::*;
22
+ //!
23
+ //! macro_rules! touch {
24
+ //! ($T:ty, $v:expr) => {{ let q = <$T>::new($v); let _c = q; assert!(q == q); }};
25
+ //! }
26
+ //!
27
+ //! touch!(Grams, 1.0); touch!(Tonnes, 1.0); touch!(Carats, 1.0);
28
+ //! touch!(Grains, 1.0); touch!(Pounds, 1.0); touch!(Ounces, 1.0);
29
+ //! touch!(Stones, 1.0); touch!(ShortTons, 1.0); touch!(LongTons, 1.0);
30
+ //! touch!(AtomicMassUnits, 1.0); touch!(SolarMasses, 1.0);
31
+ //! ```
32
+
33
+ use crate::{Quantity, Unit};
34
+ use qtty_derive::Unit;
35
+
36
+ /// Re-export from the dimension module.
37
+ pub use crate::dimension::Mass;
38
+
39
+ /// Marker trait for any [`Unit`] whose dimension is [`Mass`].
40
+ pub trait MassUnit: Unit<Dim = Mass> {}
41
+ impl<T: Unit<Dim = Mass>> MassUnit for T {}
42
+
43
+ /// Gram.
44
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
45
+ #[unit(symbol = "g", dimension = Mass, ratio = 1.0)]
46
+ pub struct Gram;
47
+ /// A quantity measured in grams.
48
+ pub type Grams = Quantity<Gram>;
49
+ /// One gram.
50
+ pub const G: Grams = Grams::new(1.0);
51
+
52
+ /// Helper macro to declare a gram-based SI mass unit.
53
+ ///
54
+ /// Each invocation of this macro defines, for a given prefix on grams:
55
+ /// - a unit struct `$name` (e.g. `Kilogram`),
56
+ /// - a shorthand type alias `$alias` (e.g. `Kg`),
57
+ /// - a quantity type `$qty` (e.g. `Kilograms`), and
58
+ /// - a constant `$one` equal to `1.0` of that quantity.
59
+ ///
60
+ /// The `$ratio` argument is the conversion factor to grams, i.e.
61
+ /// `$name::RATIO` such that `1 $sym = $ratio g`.
62
+ macro_rules! si_gram {
63
+ ($name:ident, $sym:literal, $ratio:expr, $alias:ident, $qty:ident, $one:ident) => {
64
+ #[doc = concat!("SI mass unit `", stringify!($name), "` with gram-based prefix (symbol `", $sym,"`).")]
65
+ #[doc = concat!("By definition, `1 ", $sym, " = ", stringify!($ratio), " g`.")]
66
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
67
+ #[unit(symbol = $sym, dimension = Mass, ratio = $ratio)]
68
+ pub struct $name;
69
+
70
+ #[doc = concat!("Shorthand alias for [`", stringify!($name), "`]." )]
71
+ pub type $alias = $name;
72
+
73
+ #[doc = concat!("Quantity measured in ", stringify!($name), " (",$sym,").")]
74
+ pub type $qty = Quantity<$alias>;
75
+
76
+ #[doc = concat!("Constant equal to one ", stringify!($name), " (1 ",$sym,").")]
77
+ pub const $one: $qty = $qty::new(1.0);
78
+ };
79
+ }
80
+
81
+ // Full SI prefix ladder (gram-based)
82
+ si_gram!(Yoctogram, "yg", 1e-24, Yg, Yoctograms, YG);
83
+ si_gram!(Zeptogram, "zg", 1e-21, Zg, Zeptograms, ZG);
84
+ si_gram!(Attogram, "ag", 1e-18, Ag, Attograms, AG);
85
+ si_gram!(Femtogram, "fg", 1e-15, Fg, Femtograms, FG);
86
+ si_gram!(Picogram, "pg", 1e-12, Pg, Picograms, PG);
87
+ si_gram!(Nanogram, "ng", 1e-9, Ng, Nanograms, NG);
88
+ si_gram!(Microgram, "µg", 1e-6, Ug, Micrograms, UG);
89
+ si_gram!(Milligram, "mg", 1e-3, Mg, Milligrams, MG);
90
+ si_gram!(Centigram, "cg", 1e-2, Cg, Centigrams, CG);
91
+ si_gram!(Decigram, "dg", 1e-1, Dg, Decigrams, DG);
92
+
93
+ si_gram!(Decagram, "dag", 1e1, Dag, Decagrams, DAG);
94
+ si_gram!(Hectogram, "hg", 1e2, Hg, Hectograms, HG);
95
+ si_gram!(Kilogram, "kg", 1e3, Kg, Kilograms, KG);
96
+ si_gram!(Megagram, "Mg", 1e6, MgG, Megagrams, MEGAGRAM);
97
+ si_gram!(Gigagram, "Gg", 1e9, Gg, Gigagrams, GG);
98
+ si_gram!(Teragram, "Tg", 1e12, Tg, Teragrams, TG);
99
+ si_gram!(Petagram, "Pg", 1e15, PgG, Petagrams, PETAGRAM);
100
+ si_gram!(Exagram, "Eg", 1e18, Eg, Exagrams, EG);
101
+ si_gram!(Zettagram, "Zg", 1e21, ZgG, Zettagrams, ZETTAGRAM);
102
+ si_gram!(Yottagram, "Yg", 1e24, YgG, Yottagrams, YOTTAGRAM);
103
+
104
+ /// Tonne (metric ton): `1 t = 1_000_000 g` (exact).
105
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
106
+ #[unit(symbol = "t", dimension = Mass, ratio = 1_000_000.0)]
107
+ pub struct Tonne;
108
+ /// Shorthand type alias for [`Tonne`].
109
+ pub type T = Tonne;
110
+ /// Quantity measured in tonnes.
111
+ pub type Tonnes = Quantity<T>;
112
+ /// One metric tonne.
113
+ pub const TONE: Tonnes = Tonnes::new(1.0);
114
+
115
+ /// Carat: `1 ct = 0.2 g` (exact).
116
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
117
+ #[unit(symbol = "ct", dimension = Mass, ratio = 1.0 / 5.0)]
118
+ pub struct Carat;
119
+ /// Shorthand type alias for [`Carat`].
120
+ pub type Ct = Carat;
121
+ /// Quantity measured in carats.
122
+ pub type Carats = Quantity<Ct>;
123
+ /// One carat.
124
+ pub const CT: Carats = Carats::new(1.0);
125
+
126
+ /// Grain: `1 gr = 64.79891 mg` (exact) == `0.064_798_91 g`.
127
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
128
+ #[unit(symbol = "gr", dimension = Mass, ratio = 6_479_891.0 / 1_000_000_000.0)]
129
+ pub struct Grain;
130
+ /// Shorthand type alias for [`Grain`].
131
+ pub type Gr = Grain;
132
+ /// Quantity measured in grains.
133
+ pub type Grains = Quantity<Gr>;
134
+ /// One grain.
135
+ pub const GR: Grains = Grains::new(1.0);
136
+
137
+ /// Avoirdupois pound: `1 lb = 0.45359237 kg` (exact) == `453.59237 g`.
138
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
139
+ #[unit(symbol = "lb", dimension = Mass, ratio = 45_359_237.0 / 100_000.0)]
140
+ pub struct Pound;
141
+ /// Shorthand type alias for [`Pound`].
142
+ pub type Lb = Pound;
143
+ /// Quantity measured in pounds.
144
+ pub type Pounds = Quantity<Lb>;
145
+ /// One pound.
146
+ pub const LB: Pounds = Pounds::new(1.0);
147
+
148
+ /// Avoirdupois ounce: `1 oz = 1/16 lb` (exact).
149
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
150
+ #[unit(symbol = "oz", dimension = Mass, ratio = (45_359_237.0 / 100_000.0) / 16.0)]
151
+ pub struct Ounce;
152
+ /// Shorthand type alias for [`Ounce`].
153
+ pub type Oz = Ounce;
154
+ /// Quantity measured in ounces.
155
+ pub type Ounces = Quantity<Oz>;
156
+ /// One ounce.
157
+ pub const OZ: Ounces = Ounces::new(1.0);
158
+
159
+ /// Avoirdupois stone: `1 st = 14 lb` (exact).
160
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
161
+ #[unit(symbol = "st", dimension = Mass, ratio = (45_359_237.0 / 100_000.0) * 14.0)]
162
+ pub struct Stone;
163
+ /// Shorthand type alias for [`Stone`].
164
+ pub type St = Stone;
165
+ /// Quantity measured in stones.
166
+ pub type Stones = Quantity<St>;
167
+ /// One stone.
168
+ pub const ST: Stones = Stones::new(1.0);
169
+
170
+ /// Short ton (US customary): `2000 lb` (exact given lb).
171
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
172
+ #[unit(symbol = "ton_us", dimension = Mass, ratio = (45_359_237.0 / 100_000.0) * 2000.0)]
173
+ pub struct ShortTon;
174
+ /// Quantity measured in short tons (US).
175
+ pub type ShortTons = Quantity<ShortTon>;
176
+ /// One short ton (US).
177
+ pub const TON_US: ShortTons = ShortTons::new(1.0);
178
+
179
+ /// Long ton (Imperial): `2240 lb` (exact given lb).
180
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
181
+ #[unit(symbol = "ton_uk", dimension = Mass, ratio = (45_359_237.0 / 100_000.0) * 2240.0)]
182
+ pub struct LongTon;
183
+ /// Quantity measured in long tons (UK).
184
+ pub type LongTons = Quantity<LongTon>;
185
+ /// One long ton (UK).
186
+ pub const TON_UK: LongTons = LongTons::new(1.0);
187
+
188
+ /// Unified atomic mass unit (u), a.k.a. dalton (Da).
189
+ ///
190
+ /// Stored in grams using the CODATA recommended value for `m_u` in kilograms, converted by `1 kg = 1000 g`.
191
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
192
+ #[unit(symbol = "u", dimension = Mass, ratio = 1.660_539_068_92e-24)]
193
+ pub struct AtomicMassUnit;
194
+ /// Type alias shorthand for [`AtomicMassUnit`].
195
+ pub type Dalton = AtomicMassUnit;
196
+ /// Quantity measured in atomic mass units.
197
+ pub type AtomicMassUnits = Quantity<AtomicMassUnit>;
198
+ /// One atomic mass unit.
199
+ pub const U: AtomicMassUnits = AtomicMassUnits::new(1.0);
200
+
201
+ /// Nominal solar mass (IAU 2015 Resolution B3; grams per M☉).
202
+ ///
203
+ /// This is a **conversion constant** (nominal), not a “best estimate” of the Sun’s true mass.
204
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
205
+ #[unit(symbol = "M☉", dimension = Mass, ratio = 1.988_416e33)]
206
+ pub struct SolarMass;
207
+ /// A quantity measured in solar masses.
208
+ pub type SolarMasses = Quantity<SolarMass>;
209
+ /// One nominal solar mass.
210
+ pub const MSUN: SolarMasses = SolarMasses::new(1.0);
211
+
212
+ // Generate all bidirectional From implementations between mass units.
213
+ crate::impl_unit_from_conversions!(
214
+ Gram,
215
+ Yoctogram,
216
+ Zeptogram,
217
+ Attogram,
218
+ Femtogram,
219
+ Picogram,
220
+ Nanogram,
221
+ Microgram,
222
+ Milligram,
223
+ Centigram,
224
+ Decigram,
225
+ Decagram,
226
+ Hectogram,
227
+ Kilogram,
228
+ Megagram,
229
+ Gigagram,
230
+ Teragram,
231
+ Petagram,
232
+ Exagram,
233
+ Zettagram,
234
+ Yottagram,
235
+ Tonne,
236
+ Carat,
237
+ Grain,
238
+ Pound,
239
+ Ounce,
240
+ Stone,
241
+ ShortTon,
242
+ LongTon,
243
+ AtomicMassUnit,
244
+ SolarMass
245
+ );
246
+
247
+ // Optional cross-unit operator support (`==`, `<`, etc.).
248
+ #[cfg(feature = "cross-unit-ops")]
249
+ crate::impl_unit_cross_unit_ops!(
250
+ Gram,
251
+ Yoctogram,
252
+ Zeptogram,
253
+ Attogram,
254
+ Femtogram,
255
+ Picogram,
256
+ Nanogram,
257
+ Microgram,
258
+ Milligram,
259
+ Centigram,
260
+ Decigram,
261
+ Decagram,
262
+ Hectogram,
263
+ Kilogram,
264
+ Megagram,
265
+ Gigagram,
266
+ Teragram,
267
+ Petagram,
268
+ Exagram,
269
+ Zettagram,
270
+ Yottagram,
271
+ Tonne,
272
+ Carat,
273
+ Grain,
274
+ Pound,
275
+ Ounce,
276
+ Stone,
277
+ ShortTon,
278
+ LongTon,
279
+ AtomicMassUnit,
280
+ SolarMass
281
+ );
282
+
283
+ #[cfg(test)]
284
+ mod tests {
285
+ use super::*;
286
+ use approx::{assert_abs_diff_eq, assert_relative_eq};
287
+ use proptest::prelude::*;
288
+
289
+ // ─────────────────────────────────────────────────────────────────────────────
290
+ // Basic conversions
291
+ // ─────────────────────────────────────────────────────────────────────────────
292
+
293
+ #[test]
294
+ fn gram_to_kilogram() {
295
+ let g = Grams::new(1000.0);
296
+ let kg = g.to::<Kilogram>();
297
+ assert_abs_diff_eq!(kg.value(), 1.0, epsilon = 1e-12);
298
+ }
299
+
300
+ #[test]
301
+ fn kilogram_to_gram() {
302
+ let kg = Kilograms::new(1.0);
303
+ let g = kg.to::<Gram>();
304
+ assert_abs_diff_eq!(g.value(), 1000.0, epsilon = 1e-9);
305
+ }
306
+
307
+ #[test]
308
+ fn solar_mass_to_grams() {
309
+ let sm = SolarMasses::new(1.0);
310
+ let g = sm.to::<Gram>();
311
+ // 1 M☉ ≈ 1.988416e33 grams
312
+ assert_relative_eq!(g.value(), 1.988416e33, max_relative = 1e-5);
313
+ }
314
+
315
+ #[test]
316
+ fn solar_mass_to_kilograms() {
317
+ let sm = SolarMasses::new(1.0);
318
+ let kg = sm.to::<Kilogram>();
319
+ // 1 M☉ ≈ 1.988416e30 kg
320
+ assert_relative_eq!(kg.value(), 1.988416e30, max_relative = 1e-5);
321
+ }
322
+
323
+ #[test]
324
+ fn kilograms_to_solar_mass() {
325
+ // Earth mass ≈ 5.97e24 kg ≈ 3e-6 M☉
326
+ let earth_kg = Kilograms::new(5.97e24);
327
+ let earth_sm = earth_kg.to::<SolarMass>();
328
+ assert_relative_eq!(earth_sm.value(), 3.0e-6, max_relative = 0.01);
329
+ }
330
+
331
+ // ─────────────────────────────────────────────────────────────────────────────
332
+ // Solar mass sanity checks
333
+ // ─────────────────────────────────────────────────────────────────────────────
334
+
335
+ #[test]
336
+ fn solar_mass_ratio_sanity() {
337
+ // 1 M☉ = 1.988416e33 g, so RATIO should be that value
338
+ assert_relative_eq!(SolarMass::RATIO, 1.988416e33, max_relative = 1e-5);
339
+ }
340
+
341
+ #[test]
342
+ fn solar_mass_order_of_magnitude() {
343
+ // The Sun's mass is about 2e30 kg
344
+ let sun = SolarMasses::new(1.0);
345
+ let kg = sun.to::<Kilogram>();
346
+ assert!(kg.value() > 1e30);
347
+ assert!(kg.value() < 1e31);
348
+ }
349
+
350
+ // ─────────────────────────────────────────────────────────────────────────────
351
+ // Roundtrip conversions
352
+ // ─────────────────────────────────────────────────────────────────────────────
353
+
354
+ #[test]
355
+ fn roundtrip_g_kg() {
356
+ let original = Grams::new(5000.0);
357
+ let converted = original.to::<Kilogram>();
358
+ let back = converted.to::<Gram>();
359
+ assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-9);
360
+ }
361
+
362
+ #[test]
363
+ fn roundtrip_kg_solar() {
364
+ let original = Kilograms::new(1e30);
365
+ let converted = original.to::<SolarMass>();
366
+ let back = converted.to::<Kilogram>();
367
+ assert_relative_eq!(back.value(), original.value(), max_relative = 1e-12);
368
+ }
369
+
370
+ // ─────────────────────────────────────────────────────────────────────────────
371
+ // Property-based tests
372
+ // ─────────────────────────────────────────────────────────────────────────────
373
+
374
+ proptest! {
375
+ #[test]
376
+ fn prop_roundtrip_g_kg(g in 1e-6..1e6f64) {
377
+ let original = Grams::new(g);
378
+ let converted = original.to::<Kilogram>();
379
+ let back = converted.to::<Gram>();
380
+ prop_assert!((back.value() - original.value()).abs() < 1e-9 * g.abs().max(1.0));
381
+ }
382
+
383
+ #[test]
384
+ fn prop_g_kg_ratio(g in 1e-6..1e6f64) {
385
+ let grams = Grams::new(g);
386
+ let kg = grams.to::<Kilogram>();
387
+ // 1000 g = 1 kg
388
+ prop_assert!((grams.value() / kg.value() - 1000.0).abs() < 1e-9);
389
+ }
390
+ }
391
+
392
+ // ─── Non-SI mass units ──────────────────────────────────────────────────
393
+
394
+ #[test]
395
+ fn tonne_to_kilogram() {
396
+ let t = Tonnes::new(1.0);
397
+ let kg = t.to::<Kilogram>();
398
+ assert_relative_eq!(kg.value(), 1_000.0, max_relative = 1e-12);
399
+ }
400
+
401
+ #[test]
402
+ fn carat_to_gram() {
403
+ let ct = Carats::new(5.0);
404
+ let g = ct.to::<Gram>();
405
+ // 1 ct = 0.2 g
406
+ assert_relative_eq!(g.value(), 1.0, max_relative = 1e-12);
407
+ }
408
+
409
+ #[test]
410
+ fn grain_to_milligram() {
411
+ let gr = Grains::new(1.0);
412
+ let mg = gr.to::<Milligram>();
413
+ // ratio in code: 6_479_891 / 1_000_000_000 g = 6.479891 mg
414
+ assert_relative_eq!(mg.value(), 6.479_891, max_relative = 1e-6);
415
+ }
416
+
417
+ #[test]
418
+ fn pound_to_gram() {
419
+ let lb = Pounds::new(1.0);
420
+ let g = lb.to::<Gram>();
421
+ // 1 lb = 453.59237 g
422
+ assert_relative_eq!(g.value(), 453.592_37, max_relative = 1e-9);
423
+ }
424
+
425
+ #[test]
426
+ fn ounce_to_gram() {
427
+ let oz = Ounces::new(16.0);
428
+ let g = oz.to::<Gram>();
429
+ // 16 oz = 1 lb = 453.59237 g
430
+ assert_relative_eq!(g.value(), 453.592_37, max_relative = 1e-9);
431
+ }
432
+
433
+ #[test]
434
+ fn stone_to_pound() {
435
+ let st = Stones::new(1.0);
436
+ let lb = st.to::<Pound>();
437
+ // 1 st = 14 lb
438
+ assert_relative_eq!(lb.value(), 14.0, max_relative = 1e-12);
439
+ }
440
+
441
+ #[test]
442
+ fn short_ton_to_pound() {
443
+ let ton = ShortTons::new(1.0);
444
+ let lb = ton.to::<Pound>();
445
+ // 1 US short ton = 2000 lb
446
+ assert_relative_eq!(lb.value(), 2000.0, max_relative = 1e-12);
447
+ }
448
+
449
+ #[test]
450
+ fn long_ton_to_pound() {
451
+ let ton = LongTons::new(1.0);
452
+ let lb = ton.to::<Pound>();
453
+ // 1 UK long ton = 2240 lb
454
+ assert_relative_eq!(lb.value(), 2240.0, max_relative = 1e-12);
455
+ }
456
+
457
+ #[test]
458
+ fn atomic_mass_unit_to_gram() {
459
+ // 1 u ≈ 1.660539e-24 g
460
+ let u = AtomicMassUnits::new(1.0);
461
+ let g = u.to::<Gram>();
462
+ assert_relative_eq!(g.value(), 1.660_539_068_92e-24, max_relative = 1e-6);
463
+ }
464
+
465
+ // ─── SI gram-prefix sampling ────────────────────────────────────────────
466
+
467
+ #[test]
468
+ fn milligram_to_gram() {
469
+ let mg = Milligrams::new(1000.0);
470
+ let g = mg.to::<Gram>();
471
+ assert_relative_eq!(g.value(), 1.0, max_relative = 1e-12);
472
+ }
473
+
474
+ #[test]
475
+ fn microgram_to_milligram() {
476
+ let ug = Micrograms::new(1000.0);
477
+ let mg = ug.to::<Milligram>();
478
+ assert_relative_eq!(mg.value(), 1.0, max_relative = 1e-12);
479
+ }
480
+
481
+ #[test]
482
+ fn symbols_are_correct() {
483
+ assert_eq!(Kilogram::SYMBOL, "kg");
484
+ assert_eq!(Gram::SYMBOL, "g");
485
+ assert_eq!(Pound::SYMBOL, "lb");
486
+ assert_eq!(Tonne::SYMBOL, "t");
487
+ }
488
+ }
@@ -0,0 +1,26 @@
1
+ //! Predefined unit modules grouped by dimension.
2
+ //!
3
+ //! `qtty-core` ships a small set of built-in units so that conversions and formatting work out of the box without
4
+ //! downstream crates having to fight Rust’s orphan rules.
5
+ //!
6
+ //! ## Modules
7
+ //!
8
+ //! - [`angular`]: angle units plus wrapping and trig helpers.
9
+ //! - [`time`]: time units (SI second is canonical scaling unit).
10
+ //! - [`length`]: length units (SI metre is canonical scaling unit) plus astronomy/geodesy helpers.
11
+ //! - [`mass`]: mass units (gram is canonical scaling unit).
12
+ //! - [`power`]: power units (watt is canonical scaling unit).
13
+ //! - [`velocity`]: velocity aliases (`Length / Time`) built from [`length`] and [`time`].
14
+ //! - [`frequency`]: angular frequency aliases (`Angular / Time`) built from [`angular`] and [`time`].
15
+ //! - [`unitless`]: helpers for dimensionless quantities.
16
+
17
+ pub mod angular;
18
+ pub mod area;
19
+ pub mod frequency;
20
+ pub mod length;
21
+ pub mod mass;
22
+ pub mod power;
23
+ pub mod time;
24
+ pub mod unitless;
25
+ pub mod velocity;
26
+ pub mod volume;