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,243 @@
1
+ //! Area units.
2
+ //!
3
+ //! The canonical scaling unit for this dimension is the **square metre** (`SquareMeter::RATIO == 1.0`).
4
+ //! All other area units are expressed as exact ratios to square metres.
5
+ //!
6
+ //! This module provides:
7
+ //!
8
+ //! - **Metric squares**: square millimetre, square centimetre, square metre, square kilometre.
9
+ //! - **Land measurement**: hectare, are.
10
+ //! - **Imperial/US**: square inch, square foot, square yard, square mile, acre.
11
+ //!
12
+ //! Area units can also arise *automatically* from multiplying two length quantities:
13
+ //!
14
+ //! ```rust
15
+ //! use qtty_core::length::{Meter, Meters};
16
+ //! use qtty_core::area::{SquareMeters, SquareMeter};
17
+ //! use qtty_core::Prod;
18
+ //!
19
+ //! let side = Meters::new(5.0);
20
+ //! let area_prod = side * side; // Quantity<Prod<Meter, Meter>>
21
+ //! let area: SquareMeters = area_prod.to(); // Convert to named area unit
22
+ //! assert!((area.value() - 25.0).abs() < 1e-12);
23
+ //! ```
24
+ //!
25
+ //! ## All area units
26
+ //!
27
+ //! ```rust
28
+ //! use qtty_core::area::*;
29
+ //!
30
+ //! macro_rules! touch {
31
+ //! ($T:ty, $v:expr) => {{ let q = <$T>::new($v); let _c = q; assert!(q == q); }};
32
+ //! }
33
+ //!
34
+ //! touch!(SquareMeters, 1.0); touch!(SquareKilometers, 1.0);
35
+ //! touch!(SquareCentimeters, 1.0);touch!(SquareMillimeters, 1.0);
36
+ //! touch!(Hectares, 1.0); touch!(Ares, 1.0);
37
+ //! touch!(SquareInches, 1.0); touch!(SquareFeet, 1.0);
38
+ //! touch!(SquareYards, 1.0); touch!(SquareMiles, 1.0);
39
+ //! touch!(Acres, 1.0);
40
+ //! ```
41
+
42
+ use crate::{Quantity, Unit};
43
+ use qtty_derive::Unit;
44
+
45
+ /// Re-export the area dimension from the dimension module.
46
+ pub use crate::dimension::Area;
47
+
48
+ /// Marker trait for any [`Unit`] whose dimension is [`Area`].
49
+ pub trait AreaUnit: Unit<Dim = Area> {}
50
+ impl<T: Unit<Dim = Area>> AreaUnit for T {}
51
+
52
+ // ─────────────────────────────────────────────────────────────────────────────
53
+ // SI / metric area units
54
+ // ─────────────────────────────────────────────────────────────────────────────
55
+
56
+ /// Square metre (SI derived unit of area).
57
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
58
+ #[unit(symbol = "m²", dimension = Area, ratio = 1.0)]
59
+ pub struct SquareMeter;
60
+ /// A quantity measured in square metres.
61
+ pub type SquareMeters = Quantity<SquareMeter>;
62
+
63
+ /// Square kilometre (`1e6 m²`).
64
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
65
+ #[unit(symbol = "km²", dimension = Area, ratio = 1e6)]
66
+ pub struct SquareKilometer;
67
+ /// A quantity measured in square kilometres.
68
+ pub type SquareKilometers = Quantity<SquareKilometer>;
69
+
70
+ /// Square centimetre (`1e-4 m²`).
71
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
72
+ #[unit(symbol = "cm²", dimension = Area, ratio = 1e-4)]
73
+ pub struct SquareCentimeter;
74
+ /// A quantity measured in square centimetres.
75
+ pub type SquareCentimeters = Quantity<SquareCentimeter>;
76
+
77
+ /// Square millimetre (`1e-6 m²`).
78
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
79
+ #[unit(symbol = "mm²", dimension = Area, ratio = 1e-6)]
80
+ pub struct SquareMillimeter;
81
+ /// A quantity measured in square millimetres.
82
+ pub type SquareMillimeters = Quantity<SquareMillimeter>;
83
+
84
+ // ─────────────────────────────────────────────────────────────────────────────
85
+ // Land measurement
86
+ // ─────────────────────────────────────────────────────────────────────────────
87
+
88
+ /// Hectare (`10 000 m²`).
89
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
90
+ #[unit(symbol = "ha", dimension = Area, ratio = 1e4)]
91
+ pub struct Hectare;
92
+ /// A quantity measured in hectares.
93
+ pub type Hectares = Quantity<Hectare>;
94
+
95
+ /// Are (`100 m²`).
96
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
97
+ #[unit(symbol = "a", dimension = Area, ratio = 100.0)]
98
+ pub struct Are;
99
+ /// A quantity measured in ares.
100
+ pub type Ares = Quantity<Are>;
101
+
102
+ // ─────────────────────────────────────────────────────────────────────────────
103
+ // Imperial / US customary area units
104
+ // ─────────────────────────────────────────────────────────────────────────────
105
+
106
+ /// Square inch (`6.4516e-4 m²`, exact: `0.0254² m²`).
107
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
108
+ #[unit(symbol = "in²", dimension = Area, ratio = 6.4516e-4)]
109
+ pub struct SquareInch;
110
+ /// A quantity measured in square inches.
111
+ pub type SquareInches = Quantity<SquareInch>;
112
+
113
+ /// Square foot (`0.09290304 m²`, exact: `0.3048² m²`).
114
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
115
+ #[unit(symbol = "ft²", dimension = Area, ratio = 0.09290304)]
116
+ pub struct SquareFoot;
117
+ /// A quantity measured in square feet.
118
+ pub type SquareFeet = Quantity<SquareFoot>;
119
+
120
+ /// Square yard (`0.83612736 m²`, exact: `0.9144² m²`).
121
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
122
+ #[unit(symbol = "yd²", dimension = Area, ratio = 0.83612736)]
123
+ pub struct SquareYard;
124
+ /// A quantity measured in square yards.
125
+ pub type SquareYards = Quantity<SquareYard>;
126
+
127
+ /// Square mile (`2_589_988.110336 m²`, exact: `1609.344² m²`).
128
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
129
+ #[unit(symbol = "mi²", dimension = Area, ratio = 2_589_988.110_336)]
130
+ pub struct SquareMile;
131
+ /// A quantity measured in square miles.
132
+ pub type SquareMiles = Quantity<SquareMile>;
133
+
134
+ /// Acre (exactly `4046.8564224 m²`).
135
+ #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
136
+ #[unit(symbol = "ac", dimension = Area, ratio = 4_046.856_422_4)]
137
+ pub struct Acre;
138
+ /// A quantity measured in acres.
139
+ pub type Acres = Quantity<Acre>;
140
+
141
+ #[cfg(test)]
142
+ mod tests {
143
+ use super::*;
144
+ use approx::assert_abs_diff_eq;
145
+
146
+ #[test]
147
+ fn sqm_to_sqkm() {
148
+ let a = SquareMeters::new(1_000_000.0);
149
+ let b: SquareKilometers = a.to();
150
+ assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
151
+ }
152
+
153
+ #[test]
154
+ fn hectare_to_sqm() {
155
+ let a = Hectares::new(1.0);
156
+ let b: SquareMeters = a.to();
157
+ assert_abs_diff_eq!(b.value(), 10_000.0, epsilon = 1e-9);
158
+ }
159
+
160
+ #[test]
161
+ fn acre_to_hectare() {
162
+ let a = Acres::new(1.0);
163
+ let b: Hectares = a.to();
164
+ assert_abs_diff_eq!(b.value(), 0.404_685_642_24, epsilon = 1e-9);
165
+ }
166
+
167
+ #[test]
168
+ fn sqft_to_sqm() {
169
+ let a = SquareFeet::new(1.0);
170
+ let b: SquareMeters = a.to();
171
+ assert_abs_diff_eq!(b.value(), 0.092_903_04, epsilon = 1e-9);
172
+ }
173
+
174
+ #[test]
175
+ fn length_product_to_area() {
176
+ use crate::length::{Meter, Meters};
177
+ use crate::Prod;
178
+
179
+ let side = Meters::new(5.0);
180
+ let area_prod: Quantity<Prod<Meter, Meter>> = side * side;
181
+ let area: SquareMeters = area_prod.to();
182
+ assert_abs_diff_eq!(area.value(), 25.0, epsilon = 1e-12);
183
+ }
184
+
185
+ #[test]
186
+ fn sqmile_to_sqkm() {
187
+ let a = SquareMiles::new(1.0);
188
+ let b: SquareKilometers = a.to();
189
+ assert_abs_diff_eq!(b.value(), 2.589_988_110_336, epsilon = 1e-6);
190
+ }
191
+
192
+ #[test]
193
+ fn sqcm_to_sqm() {
194
+ let a = SquareCentimeters::new(10_000.0);
195
+ let b: SquareMeters = a.to();
196
+ assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
197
+ }
198
+
199
+ #[test]
200
+ fn sqmm_to_sqcm() {
201
+ let a = SquareMillimeters::new(100.0);
202
+ let b: SquareCentimeters = a.to();
203
+ assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
204
+ }
205
+
206
+ #[test]
207
+ fn are_to_sqm() {
208
+ let a = Ares::new(1.0);
209
+ let b: SquareMeters = a.to();
210
+ assert_abs_diff_eq!(b.value(), 100.0, epsilon = 1e-12);
211
+ }
212
+
213
+ #[test]
214
+ fn sqinch_to_sqcm() {
215
+ let a = SquareInches::new(1.0);
216
+ let b: SquareCentimeters = a.to();
217
+ // 1 in² = 6.4516 cm²
218
+ assert_abs_diff_eq!(b.value(), 6.4516, epsilon = 1e-9);
219
+ }
220
+
221
+ #[test]
222
+ fn sqyard_to_sqm() {
223
+ let a = SquareYards::new(1.0);
224
+ let b: SquareMeters = a.to();
225
+ assert_abs_diff_eq!(b.value(), 0.836_127_36, epsilon = 1e-9);
226
+ }
227
+
228
+ #[test]
229
+ fn roundtrip_sqcm_sqm() {
230
+ let original = SquareCentimeters::new(250.0);
231
+ let converted = original.to::<SquareMeter>();
232
+ let back = converted.to::<SquareCentimeter>();
233
+ assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-10);
234
+ }
235
+
236
+ #[test]
237
+ fn symbols_are_correct() {
238
+ assert_eq!(SquareMeter::SYMBOL, "m²");
239
+ assert_eq!(Hectare::SYMBOL, "ha");
240
+ assert_eq!(Acre::SYMBOL, "ac");
241
+ assert_eq!(SquareInch::SYMBOL, "in²");
242
+ }
243
+ }
@@ -0,0 +1,179 @@
1
+ //! Angular frequency unit aliases (`Angular / Time`).
2
+ //!
3
+ //! This module provides a **dimension alias** [`Frequency`].
4
+ //!
5
+ //! ```rust
6
+ //! use qtty_core::angular::{Degree, Radian};
7
+ //! use qtty_core::time::Day;
8
+ //! use qtty_core::frequency::Frequency;
9
+ //!
10
+ //! let f: Frequency<Degree, Day> = Frequency::new(180.0);
11
+ //! let f_rad: Frequency<Radian, Day> = f.to();
12
+ //! assert!((f_rad.value() - core::f64::consts::PI).abs() < 1e-12);
13
+ //! ```
14
+
15
+ use crate::{Per, Quantity, Unit};
16
+
17
+ /// Re-export the frequency dimension from the dimension module.
18
+ pub use crate::dimension::FrequencyDim;
19
+
20
+ /// Marker trait for any unit with frequency dimension (`Angular / Time`).
21
+ pub trait FrequencyUnit: Unit<Dim = FrequencyDim> {}
22
+ impl<T: Unit<Dim = FrequencyDim>> FrequencyUnit for T {}
23
+
24
+ /// A frequency quantity parameterized by angular and time units.
25
+ ///
26
+ /// # Examples
27
+ ///
28
+ /// ```rust
29
+ /// use qtty_core::angular::{Degree, Radian};
30
+ /// use qtty_core::time::{Second, Day};
31
+ /// use qtty_core::frequency::Frequency;
32
+ ///
33
+ /// let f1: Frequency<Degree, Second> = Frequency::new(360.0);
34
+ /// let f2: Frequency<Radian, Day> = Frequency::new(6.28);
35
+ /// ```
36
+ pub type Frequency<N, D> = Quantity<Per<N, D>>;
37
+
38
+ #[cfg(test)]
39
+ mod tests {
40
+ use super::*;
41
+ use crate::units::angular::{Degree, Degrees, MilliArcsecond, Radian};
42
+ use crate::units::time::{Day, Days, Year};
43
+ use crate::Per;
44
+ use approx::{assert_abs_diff_eq, assert_relative_eq};
45
+ use proptest::prelude::*;
46
+ use std::f64::consts::PI;
47
+
48
+ // ─────────────────────────────────────────────────────────────────────────────
49
+ // Basic frequency conversions
50
+ // ─────────────────────────────────────────────────────────────────────────────
51
+
52
+ #[test]
53
+ fn deg_per_day_to_rad_per_day() {
54
+ let f: Frequency<Degree, Day> = Frequency::new(180.0);
55
+ let f_rad: Frequency<Radian, Day> = f.to();
56
+ // 180 deg = π rad
57
+ assert_abs_diff_eq!(f_rad.value(), PI, epsilon = 1e-12);
58
+ }
59
+
60
+ #[test]
61
+ fn rad_per_day_to_deg_per_day() {
62
+ let f: Frequency<Radian, Day> = Frequency::new(PI);
63
+ let f_deg: Frequency<Degree, Day> = f.to();
64
+ assert_abs_diff_eq!(f_deg.value(), 180.0, epsilon = 1e-12);
65
+ }
66
+
67
+ #[test]
68
+ fn deg_per_day_to_deg_per_year() {
69
+ let f: Frequency<Degree, Day> = Frequency::new(1.0);
70
+ let f_year: Frequency<Degree, Year> = f.to();
71
+ // 1 deg/day = 365.2425 deg/year (tropical year)
72
+ assert_relative_eq!(f_year.value(), 365.2425, max_relative = 1e-6);
73
+ }
74
+
75
+ #[test]
76
+ fn deg_per_year_to_deg_per_day() {
77
+ let f: Frequency<Degree, Year> = Frequency::new(365.2425);
78
+ let f_day: Frequency<Degree, Day> = f.to();
79
+ assert_relative_eq!(f_day.value(), 1.0, max_relative = 1e-6);
80
+ }
81
+
82
+ #[test]
83
+ fn mas_per_day_to_deg_per_day() {
84
+ let f: Frequency<MilliArcsecond, Day> = Frequency::new(3_600_000.0);
85
+ let f_deg: Frequency<Degree, Day> = f.to();
86
+ // 3,600,000 mas = 1 deg
87
+ assert_abs_diff_eq!(f_deg.value(), 1.0, epsilon = 1e-9);
88
+ }
89
+
90
+ // ─────────────────────────────────────────────────────────────────────────────
91
+ // Per ratio behavior
92
+ // ─────────────────────────────────────────────────────────────────────────────
93
+
94
+ #[test]
95
+ fn per_ratio_deg_day() {
96
+ // Degree::RATIO = 1.0, Day::RATIO = 86400.0
97
+ // So Per<Degree, Day>::RATIO = 1.0 / 86400.0
98
+ let ratio = <Per<Degree, Day>>::RATIO;
99
+ assert_abs_diff_eq!(ratio, 1.0 / 86400.0, epsilon = 1e-12);
100
+ }
101
+
102
+ #[test]
103
+ fn per_ratio_rad_day() {
104
+ // Radian::RATIO = 180/π, Day::RATIO = 86400.0
105
+ let ratio = <Per<Radian, Day>>::RATIO;
106
+ assert_relative_eq!(ratio, (180.0 / PI) / 86400.0, max_relative = 1e-12);
107
+ }
108
+
109
+ // ─────────────────────────────────────────────────────────────────────────────
110
+ // Frequency * Time = Angle
111
+ // ─────────────────────────────────────────────────────────────────────────────
112
+
113
+ #[test]
114
+ fn frequency_times_time() {
115
+ let f: Frequency<Degree, Day> = Frequency::new(360.0);
116
+ let t: Days = Days::new(0.5);
117
+ let angle: Degrees = (f * t).to();
118
+ assert_abs_diff_eq!(angle.value(), 180.0, epsilon = 1e-9);
119
+ }
120
+
121
+ #[test]
122
+ fn time_times_frequency() {
123
+ let f: Frequency<Degree, Day> = Frequency::new(360.0);
124
+ let t: Days = Days::new(0.5);
125
+ let angle: Degrees = (t * f).to();
126
+ assert_abs_diff_eq!(angle.value(), 180.0, epsilon = 1e-9);
127
+ }
128
+
129
+ // ─────────────────────────────────────────────────────────────────────────────
130
+ // Angle / Time = Frequency
131
+ // ─────────────────────────────────────────────────────────────────────────────
132
+
133
+ #[test]
134
+ fn angle_div_time() {
135
+ let angle: Degrees = Degrees::new(360.0);
136
+ let t: Days = Days::new(1.0);
137
+ let f: Frequency<Degree, Day> = angle / t;
138
+ assert_abs_diff_eq!(f.value(), 360.0, epsilon = 1e-9);
139
+ }
140
+
141
+ // ─────────────────────────────────────────────────────────────────────────────
142
+ // Roundtrip conversions
143
+ // ─────────────────────────────────────────────────────────────────────────────
144
+
145
+ #[test]
146
+ fn roundtrip_deg_rad_per_day() {
147
+ let original: Frequency<Degree, Day> = Frequency::new(90.0);
148
+ let converted: Frequency<Radian, Day> = original.to();
149
+ let back: Frequency<Degree, Day> = converted.to();
150
+ assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-9);
151
+ }
152
+
153
+ // ─────────────────────────────────────────────────────────────────────────────
154
+ // Property-based tests
155
+ // ─────────────────────────────────────────────────────────────────────────────
156
+
157
+ proptest! {
158
+ #[test]
159
+ fn prop_roundtrip_deg_rad_per_day(f in 1e-6..1e6f64) {
160
+ let original: Frequency<Degree, Day> = Frequency::new(f);
161
+ let converted: Frequency<Radian, Day> = original.to();
162
+ let back: Frequency<Degree, Day> = converted.to();
163
+ prop_assert!((back.value() - original.value()).abs() < 1e-9 * f.abs().max(1.0));
164
+ }
165
+
166
+ #[test]
167
+ fn prop_frequency_time_roundtrip(
168
+ f_val in 1e-3..1e3f64,
169
+ t_val in 1e-3..1e3f64
170
+ ) {
171
+ let f: Frequency<Degree, Day> = Frequency::new(f_val);
172
+ let t: Days = Days::new(t_val);
173
+ let angle: Degrees = (f * t).to();
174
+ // angle / t should give back f
175
+ let f_back: Frequency<Degree, Day> = angle / t;
176
+ prop_assert!((f_back.value() - f.value()).abs() / f.value() < 1e-12);
177
+ }
178
+ }
179
+ }