unitforge 0.5.6__tar.gz → 0.5.7__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.
- {unitforge-0.5.6 → unitforge-0.5.7}/Cargo.lock +2 -2
- {unitforge-0.5.6 → unitforge-0.5.7}/Cargo.toml +2 -2
- {unitforge-0.5.6 → unitforge-0.5.7}/PKG-INFO +1 -1
- {unitforge-0.5.6 → unitforge-0.5.7}/python/unitforge/__init__.pyi +51 -1
- {unitforge-0.5.6 → unitforge-0.5.7}/src/impl_macros.rs +39 -5
- {unitforge-0.5.6 → unitforge-0.5.7}/src/internal.rs +7 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/lib.rs +2 -0
- unitforge-0.5.7/src/quantities/inverse_temperature.rs +39 -0
- unitforge-0.5.7/src/quantities/temperature.rs +59 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/relations.rs +1 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantities.rs +56 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/unitforge_macros/Cargo.toml +1 -1
- unitforge-0.5.6/src/quantities/temperature.rs +0 -38
- {unitforge-0.5.6 → unitforge-0.5.7}/.gitignore +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/.gitlab-ci.yml +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/Readme.md +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/Readme_py.md +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/install_hooks.sh +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/pyproject.toml +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/python/unitforge/__init__.py +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/python/unitforge/py.typed +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/scripts/generate_python_stubs.py +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/errors.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/prelude.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/acceleration.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/angle.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/angular_acceleration.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/angular_velocity.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/area.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/area_of_moment.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/charge.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/compliance.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/density.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/density_rate.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/density_temperature.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/density_temperature_rate.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/distance.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force_area.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force_distance.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force_div_distance_power_four.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force_per_volume.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force_stress.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/force_volume.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/frequency.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/inverse_angle.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/inverse_area.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/inverse_distance.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/inverse_stress.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/mass.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/mass_per_distance.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/molar_mass.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/pressure_rate.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/rotational_stiffness.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/specific_gas_constant.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stiffness.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/strain.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/strain_squared.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stress.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stress_cubed.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stress_per_temperature.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stress_rate.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stress_rate_per_temperature.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/stress_squared.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/time.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/universal_gas_constant.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/velocity.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/velocity_squared.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/voltage.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities/volume.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/quantities.template.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/bindings/matrix3_py.template.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/bindings/vector3_py.template.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/matrix2.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/matrix2x3.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/matrix3.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/matrix3x2.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/vector2.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/src/small_linalg/vector3.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/test.sh +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/common/mod.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/matrix2.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/matrix2x3.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/matrix3.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/matrix3x2.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/ndarray_dot.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/constants.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/construction.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/enum_iter.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/metadata.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/normalization.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/plain_storage.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/relations.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/runtime_quantity.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core/scalar_edges.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_core.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/quantity_serde.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/small_linalg_edge_cases.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/small_linalg_interfaces.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/test_quantities.py +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/test_small_linalg.py +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/typecheck/mypy_smoke.py +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/vector2.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/tests/vector3.rs +0 -0
- {unitforge-0.5.6 → unitforge-0.5.7}/unitforge_macros/src/lib.rs +0 -0
|
@@ -351,7 +351,7 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
|
|
351
351
|
|
|
352
352
|
[[package]]
|
|
353
353
|
name = "unitforge"
|
|
354
|
-
version = "0.5.
|
|
354
|
+
version = "0.5.7"
|
|
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.
|
|
370
|
+
version = "0.5.7"
|
|
371
371
|
dependencies = [
|
|
372
372
|
"regex",
|
|
373
373
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "unitforge"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.7"
|
|
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.
|
|
23
|
+
unitforge_macros = { version = "0.5.7", path = "unitforge_macros" }
|
|
24
24
|
|
|
25
25
|
[features]
|
|
26
26
|
default = []
|
|
@@ -1707,6 +1707,45 @@ class InverseStress:
|
|
|
1707
1707
|
def __str__(self) -> str: ...
|
|
1708
1708
|
def __rtruediv__(self, lhs: float) -> "Stress": ...
|
|
1709
1709
|
|
|
1710
|
+
class InverseTemperatureUnit:
|
|
1711
|
+
_K: ClassVar["InverseTemperatureUnit"]
|
|
1712
|
+
_mK: ClassVar["InverseTemperatureUnit"]
|
|
1713
|
+
|
|
1714
|
+
class InverseTemperature:
|
|
1715
|
+
def __init__(self, value: float, unit: "InverseTemperatureUnit") -> None: ...
|
|
1716
|
+
@classmethod
|
|
1717
|
+
def zero(cls: Type["InverseTemperature"]) -> "InverseTemperature": ...
|
|
1718
|
+
def to(self, unit: "InverseTemperatureUnit") -> float: ...
|
|
1719
|
+
def close_abs(self, other: "InverseTemperature", threshold: "InverseTemperature") -> bool: ...
|
|
1720
|
+
def close_rel(self, other: "InverseTemperature", threshold: float) -> bool: ...
|
|
1721
|
+
def __neg__(self) -> "InverseTemperature": ...
|
|
1722
|
+
def __abs__(self) -> "InverseTemperature": ...
|
|
1723
|
+
def __add__(self, rhs: "InverseTemperature") -> "InverseTemperature": ...
|
|
1724
|
+
def __sub__(self, rhs: "InverseTemperature") -> "InverseTemperature": ...
|
|
1725
|
+
@overload
|
|
1726
|
+
def __mul__(self, rhs: float) -> "InverseTemperature": ...
|
|
1727
|
+
@overload
|
|
1728
|
+
def __mul__(self, rhs: Vector3) -> Vector3: ...
|
|
1729
|
+
@overload
|
|
1730
|
+
def __mul__(self, rhs: "Temperature") -> "Strain": ...
|
|
1731
|
+
@overload
|
|
1732
|
+
def __mul__(self, rhs: Any) -> Any: ...
|
|
1733
|
+
@overload
|
|
1734
|
+
def __truediv__(self, rhs: float) -> "InverseTemperature": ...
|
|
1735
|
+
@overload
|
|
1736
|
+
def __truediv__(self, rhs: "InverseTemperature") -> float: ...
|
|
1737
|
+
@overload
|
|
1738
|
+
def __truediv__(self, rhs: Any) -> Any: ...
|
|
1739
|
+
@overload
|
|
1740
|
+
def __mod__(self, rhs: float) -> "InverseTemperature": ...
|
|
1741
|
+
@overload
|
|
1742
|
+
def __mod__(self, rhs: "InverseTemperature") -> float: ...
|
|
1743
|
+
@overload
|
|
1744
|
+
def __mod__(self, rhs: Any) -> Any: ...
|
|
1745
|
+
def __rmul__(self, rhs: float) -> "InverseTemperature": ...
|
|
1746
|
+
def __repr__(self) -> str: ...
|
|
1747
|
+
def __str__(self) -> str: ...
|
|
1748
|
+
|
|
1710
1749
|
class MassUnit:
|
|
1711
1750
|
mg: ClassVar["MassUnit"]
|
|
1712
1751
|
g: ClassVar["MassUnit"]
|
|
@@ -2074,14 +2113,22 @@ class Strain:
|
|
|
2074
2113
|
@overload
|
|
2075
2114
|
def __truediv__(self, rhs: float) -> "Strain": ...
|
|
2076
2115
|
@overload
|
|
2116
|
+
def __truediv__(self, rhs: "InverseTemperature") -> "Temperature": ...
|
|
2117
|
+
@overload
|
|
2077
2118
|
def __truediv__(self, rhs: "Strain") -> float: ...
|
|
2078
2119
|
@overload
|
|
2120
|
+
def __truediv__(self, rhs: "Temperature") -> "InverseTemperature": ...
|
|
2121
|
+
@overload
|
|
2079
2122
|
def __truediv__(self, rhs: Any) -> Any: ...
|
|
2080
2123
|
@overload
|
|
2081
2124
|
def __mod__(self, rhs: float) -> "Strain": ...
|
|
2082
2125
|
@overload
|
|
2126
|
+
def __mod__(self, rhs: "InverseTemperature") -> "Temperature": ...
|
|
2127
|
+
@overload
|
|
2083
2128
|
def __mod__(self, rhs: "Strain") -> float: ...
|
|
2084
2129
|
@overload
|
|
2130
|
+
def __mod__(self, rhs: "Temperature") -> "InverseTemperature": ...
|
|
2131
|
+
@overload
|
|
2085
2132
|
def __mod__(self, rhs: Any) -> Any: ...
|
|
2086
2133
|
def __rmul__(self, rhs: float) -> "Strain": ...
|
|
2087
2134
|
def __repr__(self) -> str: ...
|
|
@@ -2520,7 +2567,8 @@ class StressSquared:
|
|
|
2520
2567
|
class TemperatureUnit:
|
|
2521
2568
|
K: ClassVar["TemperatureUnit"]
|
|
2522
2569
|
mK: ClassVar["TemperatureUnit"]
|
|
2523
|
-
|
|
2570
|
+
C: ClassVar["TemperatureUnit"]
|
|
2571
|
+
F: ClassVar["TemperatureUnit"]
|
|
2524
2572
|
|
|
2525
2573
|
class Temperature:
|
|
2526
2574
|
def __init__(self, value: float, unit: "TemperatureUnit") -> None: ...
|
|
@@ -2542,6 +2590,8 @@ class Temperature:
|
|
|
2542
2590
|
@overload
|
|
2543
2591
|
def __mul__(self, rhs: "DensityRate") -> "DensityTemperatureRate": ...
|
|
2544
2592
|
@overload
|
|
2593
|
+
def __mul__(self, rhs: "InverseTemperature") -> "Strain": ...
|
|
2594
|
+
@overload
|
|
2545
2595
|
def __mul__(self, rhs: "SpecificGasConstant") -> "VelocitySquared": ...
|
|
2546
2596
|
@overload
|
|
2547
2597
|
def __mul__(self, rhs: "StressPerTemperature") -> "Stress": ...
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
#[macro_export]
|
|
2
2
|
macro_rules! impl_quantity {
|
|
3
3
|
($type:ident, $unit:ident, $display_units:expr) => {
|
|
4
|
+
$crate::impl_quantity!(
|
|
5
|
+
$type,
|
|
6
|
+
$unit,
|
|
7
|
+
$display_units,
|
|
8
|
+
$crate::internal::zero_offset_const
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
// `$offset_fn` converts a unit variant to the additive term (in base SI
|
|
12
|
+
// units) needed by affine units such as Celsius/Fahrenheit, where
|
|
13
|
+
// `base_value = value * scale + offset`. It defaults to always-zero above,
|
|
14
|
+
// so every purely multiplicative quantity is unaffected.
|
|
15
|
+
($type:ident, $unit:ident, $display_units:expr, $offset_fn:path) => {
|
|
4
16
|
use core::cmp::Ordering;
|
|
5
17
|
use core::fmt;
|
|
6
18
|
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
|
@@ -136,6 +148,16 @@ macro_rules! impl_quantity {
|
|
|
136
148
|
impl $type {
|
|
137
149
|
pub const fn new(value: f64, unit: $unit) -> Self {
|
|
138
150
|
let (unit_multiplier, unit_power) = unit.base_per_x_const();
|
|
151
|
+
// Affine units fold their offset in here: shifting `value` by
|
|
152
|
+
// `offset / scale` before the existing pure-scale math below
|
|
153
|
+
// yields `value * scale + offset` in base SI units. A no-op
|
|
154
|
+
// (adds 0.0) for every purely multiplicative unit.
|
|
155
|
+
let value = value
|
|
156
|
+
+ $offset_fn(unit)
|
|
157
|
+
/ $crate::internal::quantity_parts_to_value_const(
|
|
158
|
+
unit_multiplier,
|
|
159
|
+
unit_power,
|
|
160
|
+
);
|
|
139
161
|
#[cfg(not(any(feature = "storage-f64", feature = "storage-f32")))]
|
|
140
162
|
{
|
|
141
163
|
let (multiplier, power) =
|
|
@@ -288,19 +310,31 @@ macro_rules! impl_quantity {
|
|
|
288
310
|
}
|
|
289
311
|
|
|
290
312
|
fn to(&self, unit: Self::Unit) -> f64 {
|
|
313
|
+
let offset = $offset_fn(unit);
|
|
291
314
|
#[cfg(not(any(feature = "storage-f64", feature = "storage-f32")))]
|
|
292
315
|
{
|
|
293
|
-
if
|
|
294
|
-
|
|
316
|
+
if offset == 0.0 {
|
|
317
|
+
if self.multiplier == 0.0 {
|
|
318
|
+
return 0.0;
|
|
319
|
+
}
|
|
320
|
+
let (unit_multiplier, unit_power) = unit.base_per_x();
|
|
321
|
+
return self.multiplier / unit_multiplier
|
|
322
|
+
* $crate::internal::pow10_delta(self.power, unit_power);
|
|
295
323
|
}
|
|
324
|
+
// Affine units (non-zero offset) go through `as_f64()`
|
|
325
|
+
// instead of the mantissa/power fast path above, since
|
|
326
|
+
// subtracting `offset` needs the plain base-SI value.
|
|
296
327
|
let (unit_multiplier, unit_power) = unit.base_per_x();
|
|
297
|
-
self.
|
|
298
|
-
|
|
328
|
+
(self.as_f64() - offset)
|
|
329
|
+
/ $crate::internal::quantity_parts_to_value_const(
|
|
330
|
+
unit_multiplier,
|
|
331
|
+
unit_power,
|
|
332
|
+
)
|
|
299
333
|
}
|
|
300
334
|
#[cfg(any(feature = "storage-f64", feature = "storage-f32"))]
|
|
301
335
|
{
|
|
302
336
|
let (unit_multiplier, unit_power) = unit.base_per_x();
|
|
303
|
-
self.as_f64()
|
|
337
|
+
(self.as_f64() - offset)
|
|
304
338
|
/ $crate::internal::quantity_parts_to_value(unit_multiplier, unit_power)
|
|
305
339
|
}
|
|
306
340
|
}
|
|
@@ -7,6 +7,13 @@ const SQRT_10: f64 = 3.162_277_660_168_379;
|
|
|
7
7
|
#[cfg(not(any(feature = "storage-f64", feature = "storage-f32")))]
|
|
8
8
|
const INV_SQRT_10: f64 = 0.31622776601683794;
|
|
9
9
|
|
|
10
|
+
/// Default `PhysicsUnit` offset hook used by `impl_quantity!` for purely
|
|
11
|
+
/// multiplicative units. Affine units (e.g. temperature's Celsius/Fahrenheit)
|
|
12
|
+
/// supply their own `const fn(Unit) -> f64` instead.
|
|
13
|
+
pub const fn zero_offset_const<U: Copy>(_unit: U) -> f64 {
|
|
14
|
+
0.0
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
const fn clamp_power_const(power: i64) -> i32 {
|
|
11
18
|
if power < -(MAX_ABS_QUANTITY_POWER as i64) {
|
|
12
19
|
-MAX_ABS_QUANTITY_POWER
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
use crate::impl_macros::macros::*;
|
|
2
|
+
|
|
3
|
+
#[cfg_attr(feature = "strum", derive(EnumIter))]
|
|
4
|
+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
5
|
+
#[derive(Copy, Clone, PartialEq, Debug, Hash, Eq)]
|
|
6
|
+
#[cfg_attr(feature = "pyo3", pyclass(eq, eq_int, from_py_object))]
|
|
7
|
+
pub enum InverseTemperatureUnit {
|
|
8
|
+
_K,
|
|
9
|
+
_mK,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
impl InverseTemperatureUnit {
|
|
13
|
+
pub const fn base_per_x_const(self) -> (f64, i32) {
|
|
14
|
+
match self {
|
|
15
|
+
InverseTemperatureUnit::_K => (1., 0),
|
|
16
|
+
InverseTemperatureUnit::_mK => (1., 3),
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
impl PhysicsUnit for InverseTemperatureUnit {
|
|
22
|
+
fn name(&self) -> &str {
|
|
23
|
+
match &self {
|
|
24
|
+
InverseTemperatureUnit::_K => "1/K",
|
|
25
|
+
InverseTemperatureUnit::_mK => "1/mK",
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fn base_per_x(&self) -> (f64, i32) {
|
|
30
|
+
(*self).base_per_x_const()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
impl_quantity!(
|
|
35
|
+
InverseTemperature,
|
|
36
|
+
InverseTemperatureUnit,
|
|
37
|
+
[InverseTemperatureUnit::_K]
|
|
38
|
+
);
|
|
39
|
+
impl_div_with_self_to_f64!(InverseTemperature);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
use crate::impl_macros::macros::*;
|
|
2
|
+
|
|
3
|
+
#[cfg_attr(feature = "strum", derive(EnumIter))]
|
|
4
|
+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
5
|
+
#[derive(Copy, Clone, PartialEq, Debug, Hash, Eq)]
|
|
6
|
+
#[cfg_attr(feature = "pyo3", pyclass(eq, eq_int, from_py_object))]
|
|
7
|
+
pub enum TemperatureUnit {
|
|
8
|
+
K,
|
|
9
|
+
mK,
|
|
10
|
+
C,
|
|
11
|
+
F,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl TemperatureUnit {
|
|
15
|
+
/// Scale only, in the sense of `kelvin = value * multiplier * 10^power + base_offset_const()`.
|
|
16
|
+
/// Celsius shares Kelvin's scale; Fahrenheit's degree is 5/9 of a Kelvin.
|
|
17
|
+
pub const fn base_per_x_const(self) -> (f64, i32) {
|
|
18
|
+
match self {
|
|
19
|
+
TemperatureUnit::K => (1., 0),
|
|
20
|
+
TemperatureUnit::mK => (1., -3),
|
|
21
|
+
TemperatureUnit::C => (1., 0),
|
|
22
|
+
TemperatureUnit::F => (5. / 9., 0),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// Additive term (kelvin) applied on top of `base_per_x_const`'s scaling,
|
|
27
|
+
/// i.e. `kelvin = value * scale + base_offset_const()`. Zero for every
|
|
28
|
+
/// linear unit; only Celsius/Fahrenheit are affine.
|
|
29
|
+
pub const fn base_offset_const(self) -> f64 {
|
|
30
|
+
match self {
|
|
31
|
+
TemperatureUnit::K | TemperatureUnit::mK => 0.0,
|
|
32
|
+
TemperatureUnit::C => 273.15,
|
|
33
|
+
TemperatureUnit::F => 273.15 - 32. * 5. / 9.,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
impl PhysicsUnit for TemperatureUnit {
|
|
39
|
+
fn name(&self) -> &str {
|
|
40
|
+
match &self {
|
|
41
|
+
TemperatureUnit::K => "K",
|
|
42
|
+
TemperatureUnit::mK => "mK",
|
|
43
|
+
TemperatureUnit::C => "°C",
|
|
44
|
+
TemperatureUnit::F => "°F",
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fn base_per_x(&self) -> (f64, i32) {
|
|
49
|
+
(*self).base_per_x_const()
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
impl_quantity!(
|
|
54
|
+
Temperature,
|
|
55
|
+
TemperatureUnit,
|
|
56
|
+
[TemperatureUnit::K],
|
|
57
|
+
TemperatureUnit::base_offset_const
|
|
58
|
+
);
|
|
59
|
+
impl_div_with_self_to_f64!(Temperature);
|
|
@@ -72,6 +72,7 @@ impl_mul_relation_with_other!(DensityRate, Temperature, DensityTemperatureRate);
|
|
|
72
72
|
impl_mul_relation_with_other!(SpecificGasConstant, DensityTemperatureRate, StressRate);
|
|
73
73
|
impl_mul_relation_with_other!(DensityRate, SpecificGasConstant, StressRatePerTemperature);
|
|
74
74
|
impl_mul_relation_with_other!(StressRatePerTemperature, Temperature, StressRate);
|
|
75
|
+
impl_mul_relation_with_other!(InverseTemperature, Temperature, Strain);
|
|
75
76
|
impl_mul!(InverseDistance, Distance, f64);
|
|
76
77
|
impl_mul!(InverseAngle, Angle, f64);
|
|
77
78
|
impl_mul!(InverseStress, Stress, f64);
|
|
@@ -262,6 +262,62 @@ mod test_thermo_and_rates {
|
|
|
262
262
|
));
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
#[test]
|
|
266
|
+
fn temperature_converts_affine_celsius_and_fahrenheit_units() {
|
|
267
|
+
let boiling = Temperature::new(100.0, TemperatureUnit::C);
|
|
268
|
+
assert!(crate::approx_eq(
|
|
269
|
+
boiling.to(TemperatureUnit::K),
|
|
270
|
+
373.15,
|
|
271
|
+
1e-9
|
|
272
|
+
));
|
|
273
|
+
assert!(crate::approx_eq(
|
|
274
|
+
boiling.to(TemperatureUnit::F),
|
|
275
|
+
212.0,
|
|
276
|
+
1e-9
|
|
277
|
+
));
|
|
278
|
+
|
|
279
|
+
let freezing = Temperature::new(32.0, TemperatureUnit::F);
|
|
280
|
+
assert!(crate::approx_eq(freezing.to(TemperatureUnit::C), 0.0, 1e-9));
|
|
281
|
+
assert!(crate::approx_eq(
|
|
282
|
+
freezing.to(TemperatureUnit::K),
|
|
283
|
+
273.15,
|
|
284
|
+
1e-9
|
|
285
|
+
));
|
|
286
|
+
|
|
287
|
+
let absolute_zero = Temperature::new(-273.15, TemperatureUnit::C);
|
|
288
|
+
assert!(crate::approx_eq(
|
|
289
|
+
absolute_zero.to(TemperatureUnit::K),
|
|
290
|
+
0.0,
|
|
291
|
+
1e-9
|
|
292
|
+
));
|
|
293
|
+
|
|
294
|
+
let minus_forty = Temperature::new(-40.0, TemperatureUnit::C);
|
|
295
|
+
assert!(crate::approx_eq(
|
|
296
|
+
minus_forty.to(TemperatureUnit::F),
|
|
297
|
+
-40.0,
|
|
298
|
+
1e-9
|
|
299
|
+
));
|
|
300
|
+
|
|
301
|
+
// Arithmetic stays defined purely in Kelvin, unaffected by the unit
|
|
302
|
+
// used at construction time.
|
|
303
|
+
let diff = boiling - freezing;
|
|
304
|
+
assert!(crate::approx_eq(diff.to(TemperatureUnit::K), 100.0, 1e-9));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
#[test]
|
|
308
|
+
fn inverse_temperature_converts_units_and_relates_to_temperature() {
|
|
309
|
+
let expansion_coefficient = InverseTemperature::new(2.0, InverseTemperatureUnit::_mK);
|
|
310
|
+
assert!(crate::approx_eq(
|
|
311
|
+
expansion_coefficient.to(InverseTemperatureUnit::_K),
|
|
312
|
+
2000.0,
|
|
313
|
+
1e-9
|
|
314
|
+
));
|
|
315
|
+
|
|
316
|
+
let temperature = Temperature::new(0.5, TemperatureUnit::mK);
|
|
317
|
+
let strain = expansion_coefficient * temperature;
|
|
318
|
+
assert!(crate::approx_eq(strain.to(StrainUnit::m_m), 1.0, 1e-9));
|
|
319
|
+
}
|
|
320
|
+
|
|
265
321
|
#[test]
|
|
266
322
|
fn molar_mass_converts_common_units() {
|
|
267
323
|
let molar_mass = MolarMass::new(28.97, MolarMassUnit::g_mol);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "unitforge_macros"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.7"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
authors = ["Dr.Q team <info@askdrq.com>", "Henrik Stromberg <henrik@askdrq.com>"]
|
|
6
6
|
description = "Proc macros for generating units, quantities, and Python bindings in unitforge"
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
use crate::impl_macros::macros::*;
|
|
2
|
-
|
|
3
|
-
#[cfg_attr(feature = "strum", derive(EnumIter))]
|
|
4
|
-
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
5
|
-
#[derive(Copy, Clone, PartialEq, Debug, Hash, Eq)]
|
|
6
|
-
#[cfg_attr(feature = "pyo3", pyclass(eq, eq_int, from_py_object))]
|
|
7
|
-
pub enum TemperatureUnit {
|
|
8
|
-
K,
|
|
9
|
-
mK,
|
|
10
|
-
kK,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
impl TemperatureUnit {
|
|
14
|
-
pub const fn base_per_x_const(self) -> (f64, i32) {
|
|
15
|
-
match self {
|
|
16
|
-
TemperatureUnit::K => (1., 0),
|
|
17
|
-
TemperatureUnit::mK => (1., -3),
|
|
18
|
-
TemperatureUnit::kK => (1., 3),
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
impl PhysicsUnit for TemperatureUnit {
|
|
24
|
-
fn name(&self) -> &str {
|
|
25
|
-
match &self {
|
|
26
|
-
TemperatureUnit::K => "K",
|
|
27
|
-
TemperatureUnit::mK => "mK",
|
|
28
|
-
TemperatureUnit::kK => "kK",
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
fn base_per_x(&self) -> (f64, i32) {
|
|
33
|
-
(*self).base_per_x_const()
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
impl_quantity!(Temperature, TemperatureUnit, [TemperatureUnit::K]);
|
|
38
|
-
impl_div_with_self_to_f64!(Temperature);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|