unitforge 0.5.12__tar.gz → 0.5.14__tar.gz

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 (120) hide show
  1. {unitforge-0.5.12 → unitforge-0.5.14}/Cargo.lock +2 -2
  2. {unitforge-0.5.12 → unitforge-0.5.14}/Cargo.toml +2 -2
  3. {unitforge-0.5.12 → unitforge-0.5.14}/PKG-INFO +15 -1
  4. {unitforge-0.5.12 → unitforge-0.5.14}/Readme.md +11 -0
  5. {unitforge-0.5.12 → unitforge-0.5.14}/Readme_py.md +14 -0
  6. {unitforge-0.5.12 → unitforge-0.5.14}/python/unitforge/__init__.pyi +7 -13
  7. {unitforge-0.5.12 → unitforge-0.5.14}/scripts/generate_python_stubs.py +3 -2
  8. {unitforge-0.5.12 → unitforge-0.5.14}/src/impl_macros.rs +164 -184
  9. unitforge-0.5.14/src/internal.rs +684 -0
  10. {unitforge-0.5.12 → unitforge-0.5.14}/src/prelude.rs +2 -20
  11. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/acceleration.rs +2 -2
  12. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/angle.rs +3 -2
  13. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/area.rs +3 -3
  14. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/density.rs +4 -4
  15. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/distance.rs +12 -12
  16. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force.rs +2 -2
  17. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force_distance.rs +2 -2
  18. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/frequency.rs +0 -33
  19. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/inverse_distance.rs +4 -4
  20. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/inverse_stress.rs +0 -17
  21. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/mass.rs +6 -6
  22. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/rotational_stiffness.rs +4 -2
  23. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stress.rs +1 -18
  24. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stress_rate.rs +1 -1
  25. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/time.rs +11 -2
  26. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/velocity.rs +9 -2
  27. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/volume.rs +3 -3
  28. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities.template.rs +20 -3
  29. {unitforge-0.5.12 → unitforge-0.5.14}/src/relations.rs +4 -5
  30. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/bindings/matrix3_py.template.rs +31 -17
  31. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/bindings/vector3_py.template.rs +46 -58
  32. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/matrix2.rs +8 -11
  33. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/matrix2x3.rs +6 -4
  34. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/matrix3.rs +8 -10
  35. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/matrix3x2.rs +6 -3
  36. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/vector2.rs +4 -3
  37. {unitforge-0.5.12 → unitforge-0.5.14}/src/small_linalg/vector3.rs +5 -5
  38. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/constants.rs +2 -2
  39. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/construction.rs +38 -0
  40. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/normalization.rs +73 -2
  41. unitforge-0.5.14/tests/quantity_core/relations.rs +205 -0
  42. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/runtime_quantity.rs +46 -0
  43. unitforge-0.5.14/tests/quantity_core/scalar_edges.rs +126 -0
  44. unitforge-0.5.14/tests/quantity_core/unit_factors.rs +125 -0
  45. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core.rs +2 -0
  46. {unitforge-0.5.12 → unitforge-0.5.14}/tests/small_linalg_edge_cases.rs +75 -0
  47. {unitforge-0.5.12 → unitforge-0.5.14}/tests/test_quantities.py +53 -0
  48. {unitforge-0.5.12 → unitforge-0.5.14}/tests/test_small_linalg.py +50 -5
  49. {unitforge-0.5.12 → unitforge-0.5.14}/unitforge_macros/Cargo.toml +1 -1
  50. {unitforge-0.5.12 → unitforge-0.5.14}/unitforge_macros/src/lib.rs +120 -17
  51. unitforge-0.5.12/src/internal.rs +0 -331
  52. unitforge-0.5.12/tests/quantity_core/relations.rs +0 -91
  53. unitforge-0.5.12/tests/quantity_core/scalar_edges.rs +0 -46
  54. {unitforge-0.5.12 → unitforge-0.5.14}/.gitignore +0 -0
  55. {unitforge-0.5.12 → unitforge-0.5.14}/.gitlab-ci.yml +0 -0
  56. {unitforge-0.5.12 → unitforge-0.5.14}/install_hooks.sh +0 -0
  57. {unitforge-0.5.12 → unitforge-0.5.14}/pyproject.toml +0 -0
  58. {unitforge-0.5.12 → unitforge-0.5.14}/python/unitforge/__init__.py +0 -0
  59. {unitforge-0.5.12 → unitforge-0.5.14}/python/unitforge/py.typed +0 -0
  60. {unitforge-0.5.12 → unitforge-0.5.14}/src/errors.rs +0 -0
  61. {unitforge-0.5.12 → unitforge-0.5.14}/src/lib.rs +0 -0
  62. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/angular_acceleration.rs +0 -0
  63. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/angular_velocity.rs +0 -0
  64. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/area_of_moment.rs +0 -0
  65. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/charge.rs +0 -0
  66. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/compliance.rs +0 -0
  67. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/density_rate.rs +0 -0
  68. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/density_temperature.rs +0 -0
  69. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/density_temperature_rate.rs +0 -0
  70. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force_area.rs +0 -0
  71. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force_div_distance_power_four.rs +0 -0
  72. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force_per_volume.rs +0 -0
  73. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force_stress.rs +0 -0
  74. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/force_volume.rs +0 -0
  75. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/heat_capacity.rs +0 -0
  76. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/heat_flux.rs +0 -0
  77. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/inverse_angle.rs +0 -0
  78. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/inverse_area.rs +0 -0
  79. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/inverse_temperature.rs +0 -0
  80. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/mass_per_distance.rs +0 -0
  81. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/molar_mass.rs +0 -0
  82. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/power.rs +0 -0
  83. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/pressure_rate.rs +0 -0
  84. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/specific_energy.rs +0 -0
  85. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/specific_gas_constant.rs +0 -0
  86. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/specific_heat_capacity.rs +0 -0
  87. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stiffness.rs +0 -0
  88. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/strain.rs +0 -0
  89. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/strain_squared.rs +0 -0
  90. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stress_cubed.rs +0 -0
  91. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stress_per_temperature.rs +0 -0
  92. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stress_rate_per_temperature.rs +0 -0
  93. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/stress_squared.rs +0 -0
  94. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/temperature.rs +0 -0
  95. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/temperature_gradient.rs +0 -0
  96. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/thermal_conductance.rs +0 -0
  97. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/thermal_conductivity.rs +0 -0
  98. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/universal_gas_constant.rs +0 -0
  99. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/velocity_squared.rs +0 -0
  100. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/voltage.rs +0 -0
  101. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/volumetric_energy_density.rs +0 -0
  102. {unitforge-0.5.12 → unitforge-0.5.14}/src/quantities/volumetric_heat_capacity.rs +0 -0
  103. {unitforge-0.5.12 → unitforge-0.5.14}/test.sh +0 -0
  104. {unitforge-0.5.12 → unitforge-0.5.14}/tests/common/mod.rs +0 -0
  105. {unitforge-0.5.12 → unitforge-0.5.14}/tests/matrix2.rs +0 -0
  106. {unitforge-0.5.12 → unitforge-0.5.14}/tests/matrix2x3.rs +0 -0
  107. {unitforge-0.5.12 → unitforge-0.5.14}/tests/matrix3.rs +0 -0
  108. {unitforge-0.5.12 → unitforge-0.5.14}/tests/matrix3_eigen.rs +0 -0
  109. {unitforge-0.5.12 → unitforge-0.5.14}/tests/matrix3x2.rs +0 -0
  110. {unitforge-0.5.12 → unitforge-0.5.14}/tests/ndarray_dot.rs +0 -0
  111. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantities.rs +0 -0
  112. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/enum_iter.rs +0 -0
  113. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/metadata.rs +0 -0
  114. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_core/plain_storage.rs +0 -0
  115. {unitforge-0.5.12 → unitforge-0.5.14}/tests/quantity_serde.rs +0 -0
  116. {unitforge-0.5.12 → unitforge-0.5.14}/tests/small_linalg_interfaces.rs +0 -0
  117. {unitforge-0.5.12 → unitforge-0.5.14}/tests/thermal_transient.rs +0 -0
  118. {unitforge-0.5.12 → unitforge-0.5.14}/tests/typecheck/mypy_smoke.py +0 -0
  119. {unitforge-0.5.12 → unitforge-0.5.14}/tests/vector2.rs +0 -0
  120. {unitforge-0.5.12 → unitforge-0.5.14}/tests/vector3.rs +0 -0
@@ -351,7 +351,7 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
351
351
 
352
352
  [[package]]
353
353
  name = "unitforge"
354
- version = "0.5.12"
354
+ version = "0.5.14"
355
355
  dependencies = [
356
356
  "ndarray",
357
357
  "num-traits",
@@ -367,7 +367,7 @@ dependencies = [
367
367
 
368
368
  [[package]]
369
369
  name = "unitforge_macros"
370
- version = "0.5.12"
370
+ version = "0.5.14"
371
371
  dependencies = [
372
372
  "regex",
373
373
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "unitforge"
3
- version = "0.5.12"
3
+ version = "0.5.14"
4
4
  edition = "2021"
5
5
  authors = ["Dr.Q team <info@askdrq.com>", "Henrik Stromberg <henrik@askdrq.com>"]
6
6
  description = "A library for unit and quantity consistent computations in Rust"
@@ -20,7 +20,7 @@ pyo3 = { version = "0.28.3", features = ["extension-module", "auto-initialize",
20
20
  numpy = { version = "0.28.0", optional = true }
21
21
  strum = { version = "0.28.0", optional = true }
22
22
  strum_macros = { version = "0.28.0", optional = true }
23
- unitforge_macros = { version = "0.5.12", path = "unitforge_macros" }
23
+ unitforge_macros = { version = "0.5.14", path = "unitforge_macros" }
24
24
 
25
25
  [features]
26
26
  default = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitforge
3
- Version: 0.5.12
3
+ Version: 0.5.14
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -72,6 +72,20 @@ f_sum = f1 + f2
72
72
  print(f_sum.to(ForceUnit.N)) # → 8.0
73
73
  ```
74
74
 
75
+ ### Comparing Quantities
76
+
77
+ `==` is tolerance-based: two quantities are equal when they differ by at most `1e-9` of the larger
78
+ magnitude. An infinity equals only itself, and NaN equals nothing. `<`, `<=`, `>` and `>=` compare
79
+ exactly, so for nearly equal values `a == b` and `a < b` can both be true. For explicit tolerances
80
+ use `a.close_abs(b, threshold)` (absolute, `threshold` is a quantity) or
81
+ `a.close_rel(b, threshold)` (relative to the mean magnitude). Quantities are not hashable.
82
+
83
+ ```python
84
+ a = Force(1.0, ForceUnit.N)
85
+ b = Force(1.0 + 1e-12, ForceUnit.N)
86
+ print(a == b, a < b) # → True True
87
+ ```
88
+
75
89
  ---
76
90
 
77
91
  ## Vector and Matrix Support
@@ -15,6 +15,17 @@
15
15
  - **Serialization**: Optional support for serde using `features = ["serde"]`; combine with `ndarray` for ndarray serialization support.
16
16
  - **python interface** Optional Python interface when building with flag pyo3; also available on pypi
17
17
 
18
+ ## Comparing quantities
19
+
20
+ `==` is tolerance-based: two quantities are equal when they differ by at most `1e-9` of the larger
21
+ magnitude. An infinity equals only itself, and NaN equals nothing. Ordering (`<`, `<=`, `>`, `>=`)
22
+ compares the stored values exactly. As a consequence:
23
+
24
+ - `==` is not transitive, and for nearly equal values `a == b` and `a < b` can both be true.
25
+ - `Hash` hashes the exact stored value, so quantities that compare equal can hash differently. Do
26
+ not rely on hash-based collections to merge nearly equal quantities.
27
+ - For an explicit, absolute tolerance use `a.is_close(&b, &tolerance)`.
28
+
18
29
  ## Contribute
19
30
 
20
31
  All contributions are welcome! Feel free to implement new quantities or define relations using `impl_macros.rs`. 🚀
@@ -56,6 +56,20 @@ f_sum = f1 + f2
56
56
  print(f_sum.to(ForceUnit.N)) # → 8.0
57
57
  ```
58
58
 
59
+ ### Comparing Quantities
60
+
61
+ `==` is tolerance-based: two quantities are equal when they differ by at most `1e-9` of the larger
62
+ magnitude. An infinity equals only itself, and NaN equals nothing. `<`, `<=`, `>` and `>=` compare
63
+ exactly, so for nearly equal values `a == b` and `a < b` can both be true. For explicit tolerances
64
+ use `a.close_abs(b, threshold)` (absolute, `threshold` is a quantity) or
65
+ `a.close_rel(b, threshold)` (relative to the mean magnitude). Quantities are not hashable.
66
+
67
+ ```python
68
+ a = Force(1.0, ForceUnit.N)
69
+ b = Force(1.0 + 1e-12, ForceUnit.N)
70
+ print(a == b, a < b) # → True True
71
+ ```
72
+
59
73
  ---
60
74
 
61
75
  ## Vector and Matrix Support
@@ -170,6 +170,7 @@ class Angle:
170
170
  def __rmul__(self, rhs: float) -> "Angle": ...
171
171
  def __repr__(self) -> str: ...
172
172
  def __str__(self) -> str: ...
173
+ def __rtruediv__(self, lhs: float) -> "InverseAngle": ...
173
174
  @staticmethod
174
175
  def pi() -> "Angle": ...
175
176
  @staticmethod
@@ -927,8 +928,6 @@ class Distance:
927
928
  @overload
928
929
  def __mul__(self, rhs: "ThermalConductivity") -> "ThermalConductance": ...
929
930
  @overload
930
- def __mul__(self, rhs: "Velocity") -> "Time": ...
931
- @overload
932
931
  def __mul__(self, rhs: "Volume") -> "AreaOfMoment": ...
933
932
  @overload
934
933
  def __mul__(self, rhs: Any) -> Any: ...
@@ -979,6 +978,7 @@ class Distance:
979
978
  def __rmul__(self, rhs: float) -> "Distance": ...
980
979
  def __repr__(self) -> str: ...
981
980
  def __str__(self) -> str: ...
981
+ def __rtruediv__(self, lhs: float) -> "InverseDistance": ...
982
982
  @staticmethod
983
983
  def a_0() -> "Distance": ...
984
984
  @staticmethod
@@ -1544,6 +1544,7 @@ class Frequency:
1544
1544
  def __rmul__(self, rhs: float) -> "Frequency": ...
1545
1545
  def __repr__(self) -> str: ...
1546
1546
  def __str__(self) -> str: ...
1547
+ def __rtruediv__(self, lhs: float) -> "Time": ...
1547
1548
 
1548
1549
  class HeatCapacityUnit:
1549
1550
  J_K: ClassVar["HeatCapacityUnit"]
@@ -1685,6 +1686,7 @@ class InverseAngle:
1685
1686
  def __rmul__(self, rhs: float) -> "InverseAngle": ...
1686
1687
  def __repr__(self) -> str: ...
1687
1688
  def __str__(self) -> str: ...
1689
+ def __rtruediv__(self, lhs: float) -> "Angle": ...
1688
1690
 
1689
1691
  class InverseAreaUnit:
1690
1692
  _msq: ClassVar["InverseAreaUnit"]
@@ -1802,6 +1804,7 @@ class InverseDistance:
1802
1804
  def __rmul__(self, rhs: float) -> "InverseDistance": ...
1803
1805
  def __repr__(self) -> str: ...
1804
1806
  def __str__(self) -> str: ...
1807
+ def __rtruediv__(self, lhs: float) -> "Distance": ...
1805
1808
 
1806
1809
  class InverseStressUnit:
1807
1810
  _Pa: ClassVar["InverseStressUnit"]
@@ -3116,26 +3119,19 @@ class Time:
3116
3119
  @overload
3117
3120
  def __truediv__(self, rhs: float) -> "Time": ...
3118
3121
  @overload
3119
- def __truediv__(self, rhs: "Distance") -> "Velocity": ...
3120
- @overload
3121
3122
  def __truediv__(self, rhs: "Time") -> float: ...
3122
3123
  @overload
3123
- def __truediv__(self, rhs: "Velocity") -> "Distance": ...
3124
- @overload
3125
3124
  def __truediv__(self, rhs: Any) -> Any: ...
3126
3125
  @overload
3127
3126
  def __mod__(self, rhs: float) -> "Time": ...
3128
3127
  @overload
3129
- def __mod__(self, rhs: "Distance") -> "Velocity": ...
3130
- @overload
3131
3128
  def __mod__(self, rhs: "Time") -> float: ...
3132
3129
  @overload
3133
- def __mod__(self, rhs: "Velocity") -> "Distance": ...
3134
- @overload
3135
3130
  def __mod__(self, rhs: Any) -> Any: ...
3136
3131
  def __rmul__(self, rhs: float) -> "Time": ...
3137
3132
  def __repr__(self) -> str: ...
3138
3133
  def __str__(self) -> str: ...
3134
+ def __rtruediv__(self, lhs: float) -> "Frequency": ...
3139
3135
 
3140
3136
  class UniversalGasConstantUnit:
3141
3137
  J_molK: ClassVar["UniversalGasConstantUnit"]
@@ -3209,8 +3205,6 @@ class Velocity:
3209
3205
  @overload
3210
3206
  def __mul__(self, rhs: "AngularVelocity") -> "Acceleration": ...
3211
3207
  @overload
3212
- def __mul__(self, rhs: "Distance") -> "Time": ...
3213
- @overload
3214
3208
  def __mul__(self, rhs: "Force") -> "Power": ...
3215
3209
  @overload
3216
3210
  def __mul__(self, rhs: "ForcePerVolume") -> "StressRate": ...
@@ -3359,7 +3353,7 @@ class VolumeUnit:
3359
3353
  incb: ClassVar["VolumeUnit"]
3360
3354
  ftcb: ClassVar["VolumeUnit"]
3361
3355
  ydcb: ClassVar["VolumeUnit"]
3362
- impgal: ClassVar["VolumeUnit"]
3356
+ gal: ClassVar["VolumeUnit"]
3363
3357
 
3364
3358
  class Volume:
3365
3359
  def __init__(self, value: float, unit: "VolumeUnit") -> None: ...
@@ -388,8 +388,9 @@ def render_quantity_stub(
388
388
  lines.append(" def __repr__(self) -> str: ...")
389
389
  lines.append(" def __str__(self) -> str: ...")
390
390
 
391
- if quantity.rtruediv_return:
392
- lines.append(f' def __rtruediv__(self, lhs: float) -> "{quantity.rtruediv_return}": ...')
391
+ rtruediv_return = operator_maps.div.get("f64", {}).get(q, quantity.rtruediv_return)
392
+ if rtruediv_return:
393
+ lines.append(f' def __rtruediv__(self, lhs: float) -> "{rtruediv_return}": ...')
393
394
 
394
395
  for const_name in quantity.constants:
395
396
  lines.extend(