diff --git a/CLAUDE.md b/CLAUDE.md
index ba9246b2..7f546bea 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -106,15 +106,22 @@ one driving it. Two layers, and both earn their place:
rather than generated, because none of it is derived from the metadata. It is what gives a
product nobody declared a type at all.
- **Nominal.** One class per dimension, per vector form and per named overload — `Length`,
- `Displacement3D`, `Weight`. This is what the exponents cannot do: **72 dimensions share 63
+ `Displacement3D`, `Weight`. This is what the exponents cannot do: **75 dimensions share 64
exponent vectors**, so `Area` and `NuclearCrossSection`, `Torque` and `Energy`, `AbsorbedDose`
- and `EquivalentDose` are each one vector between two names. 212 classes in all — 148 magnitudes,
- 27 signed scalars, and 37 vectors of two to four components.
+ and `EquivalentDose` are each one vector between two names. 220 classes in all — 153 magnitudes,
+ 29 signed scalars, and 38 vectors of two to four components.
+
+ The clearest illustration of the point is the newest: `SpecificEnergy` is `L² T⁻²`, which is
+ what `AbsorbedDose` and `EquivalentDose` already are — specific orbital energy and absorbed
+ radiation dose are both joules per kilogram, and nothing in the exponents separates the energy
+ of an orbit from a radiation dose. `SpecificAngularMomentum` lands on `L² T⁻¹` beside
+ `KinematicViscosity` the same way. Only `GravitationalParameter` brought a vector of its own,
+ `L³ T⁻²`, which is the 64th.
**Eight axes, not the seven in `dimensionalFormula` before.** `angle` is carried by
`AngularDisplacement`, `AngularVelocity`, `AngularAcceleration` and `AngularJerk`, and that is the
whole of it. Without it an angle is the same type as a ratio and an angular speed the same type as
-a frequency; with it, 61 distinct exponent vectors become 63. It is read by the C++ projection and
+a frequency; with it, 62 distinct exponent vectors become 64. It is read by the C++ projection and
carried through `DimensionInfo` on the .NET side, where `ktsu.Schema` reads it off a unit to fill
the eight exponents in its C++ reflection table.
@@ -125,8 +132,9 @@ has to pick one. Picking the first declared picked by file position, and `Dimens
first entry in `dimensions.json`, so every angular unit reported no exponents at all: the same
answer a unitless count gives, which is the conflation the axis was added to prevent. A claim that
says something now beats one that says nothing. Where several say something the first still wins,
-which decides the only other unit claimed twice: `SquareMeter` is `Area` and `NuclearCrossSection`,
-one of the 72-over-63 collisions, so the two answers differ in name and not in exponents.
+which decides the other two units claimed twice: `SquareMeter` is `Area` and `NuclearCrossSection`,
+and `SquareMeterPerSecond` is `KinematicViscosity` and `SpecificAngularMomentum`. Both are
+75-over-64 collisions, so in each the two answers differ in name and not in exponents.
**A relationship is checked before it is emitted.** The operator is written as
`Result{ lhs.value() * rhs.value() }`, so the exponents have to agree with the declared result or it
@@ -180,6 +188,15 @@ negation. No exponent can catch that: a cross product and its negation have iden
the only thing standing between the two is which dimension declares the relationship. A test pins
the sign: a force of +10 ŷ at a lever arm of +0.5 x̂ gives +5 about z, and the other order gives −5.
+Specific angular momentum is the second relationship under that rule, and it is declared the same
+way for the same reason: **h = r × v**, so `cross(Displacement3D, Velocity3D)` is declared on
+`Length`. SEM008 passes either declaration — the exponents of h and −h are identical — and
+`OrbitalMechanicsQuantityTests` pins it the way the torque test does. Declaring it on `Velocity`
+instead does not produce a wrong answer quietly; it produces no `Displacement3D.Cross(Velocity3D)`
+at all, because only the declared direction is emitted, so the test stops compiling rather than
+silently inverting. That is worth knowing: for a cross product the declaration site is checked by
+the call site, and it is the *sign* of an existing call that nothing but a test can check.
+
**How the generated code is written is measured, not chosen.** See the header of
`CppQuantityGenerator` — the same vocabulary written two ways measured 0.9896 and 1.4004 against
bare floats on MSVC while GCC and clang folded both away, so the wrong formulation passes on three
diff --git a/Semantics.Quantities.Decimal/build/ktsu.Semantics.Quantities.Decimal.props b/Semantics.Quantities.Decimal/build/ktsu.Semantics.Quantities.Decimal.props
index d6cfa001..053b32a6 100644
--- a/Semantics.Quantities.Decimal/build/ktsu.Semantics.Quantities.Decimal.props
+++ b/Semantics.Quantities.Decimal/build/ktsu.Semantics.Quantities.Decimal.props
@@ -89,6 +89,7 @@
+
@@ -180,10 +181,17 @@
+
+
+
+
+
+
+
diff --git a/Semantics.Quantities.Double/build/ktsu.Semantics.Quantities.Double.props b/Semantics.Quantities.Double/build/ktsu.Semantics.Quantities.Double.props
index 8382ba7b..f07b188e 100644
--- a/Semantics.Quantities.Double/build/ktsu.Semantics.Quantities.Double.props
+++ b/Semantics.Quantities.Double/build/ktsu.Semantics.Quantities.Double.props
@@ -89,6 +89,7 @@
+
@@ -180,10 +181,17 @@
+
+
+
+
+
+
+
diff --git a/Semantics.Quantities.Float/build/ktsu.Semantics.Quantities.Float.props b/Semantics.Quantities.Float/build/ktsu.Semantics.Quantities.Float.props
index bfc7c607..66ab02e0 100644
--- a/Semantics.Quantities.Float/build/ktsu.Semantics.Quantities.Float.props
+++ b/Semantics.Quantities.Float/build/ktsu.Semantics.Quantities.Float.props
@@ -89,6 +89,7 @@
+
@@ -180,10 +181,17 @@
+
+
+
+
+
+
+
diff --git a/Semantics.Quantities.Precise/build/ktsu.Semantics.Quantities.Precise.props b/Semantics.Quantities.Precise/build/ktsu.Semantics.Quantities.Precise.props
index 5769af15..13a8a9d0 100644
--- a/Semantics.Quantities.Precise/build/ktsu.Semantics.Quantities.Precise.props
+++ b/Semantics.Quantities.Precise/build/ktsu.Semantics.Quantities.Precise.props
@@ -89,6 +89,7 @@
+
@@ -180,10 +181,17 @@
+
+
+
+
+
+
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs
index 81fddb42..6627c778 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs
@@ -239,6 +239,9 @@ internal static class ConversionConstants
/// Standard gravity to meters per second squared: 9.80665 m/s² per g (exact by definition)
internal const double StandardGravityToMeterPerSecondSquared = 9.80665d;
+ /// Cubic kilometer per second squared to cubic meter per second squared: 1e9 m³/s² per km³/s² (exact by definition)
+ internal const double CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared = 1e9d;
+
/// Dyne to newton conversion: 1e-5 N/dyn (exact by definition)
internal const double DyneToNewtons = 1e-5d;
@@ -737,6 +740,12 @@ internal static class Values
/// StandardGravityToMeterPerSecondSquared parsed into , or when the is converted at each read.
private static readonly T? ParsedStandardGravityToMeterPerSecondSquared = StorageLiteral.Parse("9.80665");
+ /// Cubic kilometer per second squared to cubic meter per second squared: 1e9 m³/s² per km³/s² (exact by definition)
+ internal static T CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared => ParsedCubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared ?? T.CreateChecked(ConversionConstants.CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared);
+
+ /// CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared parsed into , or when the is converted at each read.
+ private static readonly T? ParsedCubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared = StorageLiteral.Parse("1e9");
+
/// Dyne to newton conversion: 1e-5 N/dyn (exact by definition)
internal static T DyneToNewtons => ParsedDyneToNewtons ?? T.CreateChecked(ConversionConstants.DyneToNewtons);
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs
index e6e85bff..de61456f 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs
@@ -110,6 +110,9 @@ public static class PhysicalDimensions
/// Physical dimension: Frequency
public static readonly DimensionInfo Frequency = new("Frequency", "T⁻¹", new Dictionary { ["time"] = -1 }, new List { "Frequency", "SamplingRate", "ClockSpeed", "Bandwidth", "Pitch" });
+ /// Physical dimension: GravitationalParameter
+ public static readonly DimensionInfo GravitationalParameter = new("GravitationalParameter", "L³ T⁻²", new Dictionary { ["length"] = 3, ["time"] = -2 }, new List { "GravitationalParameter", "StandardGravitationalParameter" });
+
/// Physical dimension: HeatTransferCoefficient
public static readonly DimensionInfo HeatTransferCoefficient = new("HeatTransferCoefficient", "M T⁻³ Θ⁻¹", new Dictionary { ["mass"] = 1, ["time"] = -3, ["temperature"] = -1 }, new List { "HeatTransferCoefficient" });
@@ -200,6 +203,12 @@ public static class PhysicalDimensions
/// Physical dimension: Snap
public static readonly DimensionInfo Snap = new("Snap", "L T⁻⁴", new Dictionary { ["length"] = 1, ["time"] = -4 }, new List { "SnapMagnitude", "Snap1D", "Snap2D", "Snap3D", "Snap4D" });
+ /// Physical dimension: SpecificAngularMomentum
+ public static readonly DimensionInfo SpecificAngularMomentum = new("SpecificAngularMomentum", "L² T⁻¹", new Dictionary { ["length"] = 2, ["time"] = -1 }, new List { "SpecificAngularMomentumMagnitude", "SpecificAngularMomentum3D" });
+
+ /// Physical dimension: SpecificEnergy
+ public static readonly DimensionInfo SpecificEnergy = new("SpecificEnergy", "L² T⁻²", new Dictionary { ["length"] = 2, ["time"] = -2 }, new List { "SpecificEnergyMagnitude", "SpecificKineticEnergy", "SpecificEnergy", "SpecificOrbitalEnergy" });
+
/// Physical dimension: SpecificHeat
public static readonly DimensionInfo SpecificHeat = new("SpecificHeat", "L² T⁻² Θ⁻¹", new Dictionary { ["length"] = 2, ["time"] = -2, ["temperature"] = -1 }, new List { "SpecificHeat", "SpecificEntropy" });
@@ -234,7 +243,7 @@ public static class PhysicalDimensions
public static readonly DimensionInfo VolumetricFlowRate = new("VolumetricFlowRate", "L³ T⁻¹", new Dictionary { ["length"] = 3, ["time"] = -1 }, new List { "VolumetricFlowRate" });
/// Gets a frozen collection of all standard physical dimensions.
- public static IReadOnlySet All = new HashSet([ AbsorbedDose, Acceleration, AcousticImpedance, AmountOfSubstance, AngularAcceleration, AngularDisplacement, AngularJerk, AngularMomentum, AngularVelocity, Area, CatalyticActivity, Concentration, Density, Dimensionless, DynamicViscosity, ElectricCapacitance, ElectricCharge, ElectricConductance, ElectricConductivity, ElectricCurrent, ElectricField, ElectricFlux, ElectricPotential, ElectricPowerDensity, ElectricResistance, Energy, Entropy, EquivalentDose, Exposure, Force, Frequency, HeatTransferCoefficient, Illuminance, Inductance, Irradiance, Jerk, KinematicViscosity, Length, Loudness, Luminance, LuminousFlux, LuminousIntensity, MagneticFlux, MagneticFluxDensity, Mass, MassFlowRate, MolarEnergy, MolarMass, MomentOfInertia, Momentum, NuclearCrossSection, OpticalPower, Permittivity, Power, Pressure, RadioactiveActivity, RateConstant, ReactionRate, Sensitivity, Sharpness, Snap, SpecificHeat, SurfaceTension, Temperature, ThermalConductivity, ThermalExpansion, ThermalResistance, Time, Torque, Velocity, Volume, VolumetricFlowRate ]);
+ public static IReadOnlySet All = new HashSet([ AbsorbedDose, Acceleration, AcousticImpedance, AmountOfSubstance, AngularAcceleration, AngularDisplacement, AngularJerk, AngularMomentum, AngularVelocity, Area, CatalyticActivity, Concentration, Density, Dimensionless, DynamicViscosity, ElectricCapacitance, ElectricCharge, ElectricConductance, ElectricConductivity, ElectricCurrent, ElectricField, ElectricFlux, ElectricPotential, ElectricPowerDensity, ElectricResistance, Energy, Entropy, EquivalentDose, Exposure, Force, Frequency, GravitationalParameter, HeatTransferCoefficient, Illuminance, Inductance, Irradiance, Jerk, KinematicViscosity, Length, Loudness, Luminance, LuminousFlux, LuminousIntensity, MagneticFlux, MagneticFluxDensity, Mass, MassFlowRate, MolarEnergy, MolarMass, MomentOfInertia, Momentum, NuclearCrossSection, OpticalPower, Permittivity, Power, Pressure, RadioactiveActivity, RateConstant, ReactionRate, Sensitivity, Sharpness, Snap, SpecificAngularMomentum, SpecificEnergy, SpecificHeat, SurfaceTension, Temperature, ThermalConductivity, ThermalExpansion, ThermalResistance, Time, Torque, Velocity, Volume, VolumetricFlowRate ]);
}
///
@@ -485,6 +494,14 @@ public interface IFrequencyUnit : IUnit
{
}
+///
+/// Marker interface implemented by every unit of the GravitationalParameter dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IGravitationalParameterUnit : IUnit
+{
+}
+
///
/// Marker interface implemented by every unit of the HeatTransferCoefficient dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -725,6 +742,22 @@ public interface ISnapUnit : IUnit
{
}
+///
+/// Marker interface implemented by every unit of the SpecificAngularMomentum dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface ISpecificAngularMomentumUnit : IUnit
+{
+}
+
+///
+/// Marker interface implemented by every unit of the SpecificEnergy dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface ISpecificEnergyUnit : IUnit
+{
+}
+
///
/// Marker interface implemented by every unit of the SpecificHeat dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs
index c855e549..1f328f07 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/AccelerationMagnitude.g.cs
@@ -147,5 +147,11 @@ namespace ktsu.Semantics.Quantities;
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
public static Duration operator /(AccelerationMagnitude left, JerkMagnitude right) => Duration.Create(left.Quantity / right.Quantity);
+
+ ///
+ /// Multiplies AccelerationMagnitude by Area to produce GravitationalParameter.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator *(AccelerationMagnitude left, Area right) => GravitationalParameter.Create(left.Quantity * right.Quantity);
}
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs
index 0bca1df8..cabd7936 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs
@@ -219,5 +219,11 @@ namespace ktsu.Semantics.Quantities;
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
public static LuminousIntensity operator *(Area left, Luminance right) => LuminousIntensity.Create(left.Quantity * right.Quantity);
+
+ ///
+ /// Multiplies Area by AccelerationMagnitude to produce GravitationalParameter.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator *(Area left, AccelerationMagnitude right) => GravitationalParameter.Create(left.Quantity * right.Quantity);
}
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs
index ca81f97b..e2a2fb4a 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Displacement3D.g.cs
@@ -118,4 +118,10 @@ public Torque3D Cross(Force3D other)
return new() { X = (Y * other.Z) - (Z * other.Y), Y = (Z * other.X) - (X * other.Z), Z = (X * other.Y) - (Y * other.X) };
}
+ /// Typed cross product: Displacement3D x Velocity3D = SpecificAngularMomentum3D.
+ public SpecificAngularMomentum3D Cross(Velocity3D other)
+ {
+ return new() { X = (Y * other.Z) - (Z * other.Y), Y = (Z * other.X) - (X * other.Z), Z = (X * other.Y) - (Y * other.X) };
+ }
+
};
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs
new file mode 100644
index 00000000..9030728f
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/GravitationalParameter.g.cs
@@ -0,0 +1,139 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Magnitude (Vector0) quantity for the GravitationalParameter dimension.
+///
+/// The numeric storage type.
+public readonly partial record struct GravitationalParameter : IVector0, T>, IPhysicalQuantity, T>
+ where T : struct, INumber
+{
+ /// Gets the value stored in this quantity (in the dimension's SI base unit).
+ public T Value => Quantity;
+
+ /// Gets whether this quantity is finite and not NaN.
+ public bool IsPhysicallyValid => PhysicalQuantityCore.IsPhysicallyValid(Quantity);
+
+ /// Gets a quantity with value zero.
+ public static GravitationalParameter Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public DimensionInfo Dimension => PhysicalDimensions.GravitationalParameter;
+
+ /// Gets the stored value, in the dimension's SI base unit.
+ public T Quantity { get; init; }
+
+ ///
+ /// Creates a quantity holding , in the SI base unit.
+ ///
+ /// The value in the SI base unit.
+ /// A new quantity holding .
+ public static GravitationalParameter Create(T value) => new() { Quantity = value };
+
+ ///
+ /// Compares this quantity to another of the same physical dimension.
+ ///
+ /// The quantity to compare against.
+ /// A negative number, zero or a positive number as this sorts before, with, or after .
+ /// When the two do not share a dimension.
+ public int CompareTo(IPhysicalQuantity other) => PhysicalQuantityCore.Compare, T>(this, other);
+
+ ///
+ /// Reports whether this quantity shares a dimension and a value with .
+ ///
+ /// The quantity to compare against.
+ /// when both dimension and value match.
+ public bool Equals(IPhysicalQuantity other) => PhysicalQuantityCore.AreEqual, T>(this, other);
+
+ /// Adds two values.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator +(GravitationalParameter left, GravitationalParameter right) => Create(left.Quantity + right.Quantity);
+
+ /// Negates a .
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator -(GravitationalParameter value) => Create(-value.Quantity);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator *(GravitationalParameter left, T right) => Create(left.Quantity * right);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator *(T left, GravitationalParameter right) => Create(left * right.Quantity);
+
+ /// Divides a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator /(GravitationalParameter left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(left.Quantity / right);
+
+ /// Divides one by another, giving the bare ratio.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static T operator /(GravitationalParameter left, GravitationalParameter right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : left.Quantity / right.Quantity;
+
+ /// Reports whether the left value sorts before the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <(GravitationalParameter left, GravitationalParameter right) => left.Quantity < right.Quantity;
+
+ /// Reports whether the left value sorts before or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <=(GravitationalParameter left, GravitationalParameter right) => left.Quantity <= right.Quantity;
+
+ /// Reports whether the left value sorts after the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >(GravitationalParameter left, GravitationalParameter right) => left.Quantity > right.Quantity;
+
+ /// Reports whether the left value sorts after or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >=(GravitationalParameter left, GravitationalParameter right) => left.Quantity >= right.Quantity;
+
+ /// Returns the stored value as text.
+ /// The value in the SI base unit, rendered by .
+ public override string ToString() => Quantity.ToString() ?? string.Empty;
+
+ ///
+ /// Creates a new from a value in CubicMeterPerSecondSquared.
+ ///
+ /// The value in CubicMeterPerSecondSquared.
+ /// A new instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static GravitationalParameter FromCubicMeterPerSecondSquared(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+
+ ///
+ /// Creates a new from a value in CubicKilometerPerSecondSquared.
+ ///
+ /// The value in CubicKilometerPerSecondSquared.
+ /// A new instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static GravitationalParameter FromCubicKilometerPerSecondSquared(T value) => Create(Vector0Guards.EnsureNonNegative((value * Units.ConversionConstants.Values.CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared), nameof(value)));
+
+ ///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-GravitationalParameter unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.IGravitationalParameterUnit unit) => unit.FromBase(Value);
+
+ ///
+ /// Subtracts two GravitationalParameter values, returning the absolute difference as a non-negative GravitationalParameter.
+ /// Magnitude subtraction stays a magnitude (per the unified-vector model).
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator -(GravitationalParameter left, GravitationalParameter right) => Create(T.Abs(left.Quantity - right.Quantity));
+
+ ///
+ /// Divides GravitationalParameter by Area to produce AccelerationMagnitude.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static AccelerationMagnitude operator /(GravitationalParameter left, Area right) => AccelerationMagnitude.Create(left.Quantity / right.Quantity);
+
+ ///
+ /// Divides GravitationalParameter by Length to produce SpecificEnergyMagnitude.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator /(GravitationalParameter left, Length right) => SpecificEnergyMagnitude.Create(left.Quantity / right.Quantity);
+}
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs
index 8bf38137..d89396dd 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Length.g.cs
@@ -257,5 +257,11 @@ namespace ktsu.Semantics.Quantities;
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
public static ForceMagnitude operator *(Length left, SurfaceTension right) => ForceMagnitude.Create(left.Quantity * right.Quantity);
+
+ ///
+ /// Multiplies Length by SpecificEnergyMagnitude to produce GravitationalParameter.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator *(Length left, SpecificEnergyMagnitude right) => GravitationalParameter.Create(left.Quantity * right.Quantity);
}
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs
new file mode 100644
index 00000000..483a3c15
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentum3D.g.cs
@@ -0,0 +1,112 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+#pragma warning disable IDE0040 // Accessibility modifiers required
+#pragma warning disable CA2225 // Operator overloads have named alternates
+
+namespace ktsu.Semantics.Quantities;
+
+using System;
+using System.Numerics;
+
+///
+/// 3D vector representation of SpecificAngularMomentum.
+///
+/// The numeric component type.
+public readonly partial record struct SpecificAngularMomentum3D : IVector3, T>
+ where T : struct, INumber
+{
+ /// Gets the X component.
+ public T X { get; init; }
+
+ /// Gets the Y component.
+ public T Y { get; init; }
+
+ /// Gets the Z component.
+ public T Z { get; init; }
+
+ /// Gets a vector with all components set to zero.
+ public static SpecificAngularMomentum3D Zero => new() { X = T.Zero, Y = T.Zero, Z = T.Zero };
+
+ /// Gets a vector with all components set to one.
+ public static SpecificAngularMomentum3D One => new() { X = T.One, Y = T.One, Z = T.One };
+
+ /// Gets the unit vector for the X-axis.
+ public static SpecificAngularMomentum3D UnitX => new() { X = T.One, Y = T.Zero, Z = T.Zero };
+
+ /// Gets the unit vector for the Y-axis.
+ public static SpecificAngularMomentum3D UnitY => new() { X = T.Zero, Y = T.One, Z = T.Zero };
+
+ /// Gets the unit vector for the Z-axis.
+ public static SpecificAngularMomentum3D UnitZ => new() { X = T.Zero, Y = T.Zero, Z = T.One };
+
+ /// Gets the magnitude of this vector as a .
+ public global::ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude Magnitude() => global::ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude.Create(Length());
+
+ /// Gets the distance to another vector as a .
+ /// The vector to measure the distance to.
+ public global::ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude DistanceTo(SpecificAngularMomentum3D other) => global::ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude.Create(Distance(other));
+
+ /// Calculates the length of the vector.
+ public T Length()
+ {
+ T sum = (X * X) + (Y * Y) + (Z * Z);
+ return StorageMath.Sqrt(sum);
+ }
+
+ /// Calculates the squared length of the vector.
+ public T LengthSquared() => (X * X) + (Y * Y) + (Z * Z);
+
+ /// Calculates the dot product of two vectors.
+ public T Dot(SpecificAngularMomentum3D other) => (X * other.X) + (Y * other.Y) + (Z * other.Z);
+
+ /// Calculates the cross product of two vectors.
+ public SpecificAngularMomentum3D Cross(SpecificAngularMomentum3D other)
+ {
+ return new() { X = (Y * other.Z) - (Z * other.Y), Y = (Z * other.X) - (X * other.Z), Z = (X * other.Y) - (Y * other.X) };
+ }
+
+ /// Calculates the distance between two vectors.
+ public T Distance(SpecificAngularMomentum3D other)
+ {
+ T dX = X - other.X;
+ T dY = Y - other.Y;
+ T dZ = Z - other.Z;
+ T sum = (dX * dX) + (dY * dY) + (dZ * dZ);
+ return StorageMath.Sqrt(sum);
+ }
+
+ /// Calculates the squared distance between two vectors.
+ public T DistanceSquared(SpecificAngularMomentum3D other)
+ {
+ T dX = X - other.X;
+ T dY = Y - other.Y;
+ T dZ = Z - other.Z;
+ return (dX * dX) + (dY * dY) + (dZ * dZ);
+ }
+
+ /// Returns a normalized version of the vector.
+ public SpecificAngularMomentum3D Normalize()
+ {
+ T len = Length();
+ return new() { X = X / len, Y = Y / len, Z = Z / len };
+ }
+
+ /// Adds two vectors.
+ public static SpecificAngularMomentum3D operator +(SpecificAngularMomentum3D left, SpecificAngularMomentum3D right) => new() { X = left.X + right.X, Y = left.Y + right.Y, Z = left.Z + right.Z };
+
+ /// Subtracts two vectors.
+ public static SpecificAngularMomentum3D operator -(SpecificAngularMomentum3D left, SpecificAngularMomentum3D right) => new() { X = left.X - right.X, Y = left.Y - right.Y, Z = left.Z - right.Z };
+
+ /// Multiplies a vector by a scalar.
+ public static SpecificAngularMomentum3D operator *(SpecificAngularMomentum3D vector, T scalar) => new() { X = vector.X * scalar, Y = vector.Y * scalar, Z = vector.Z * scalar };
+
+ /// Multiplies a scalar by a vector.
+ public static SpecificAngularMomentum3D operator *(T scalar, SpecificAngularMomentum3D vector) => new() { X = scalar * vector.X, Y = scalar * vector.Y, Z = scalar * vector.Z };
+
+ /// Divides a vector by a scalar.
+ public static SpecificAngularMomentum3D operator /(SpecificAngularMomentum3D vector, T scalar) => new() { X = vector.X / scalar, Y = vector.Y / scalar, Z = vector.Z / scalar };
+
+ /// Negates a vector.
+ public static SpecificAngularMomentum3D operator -(SpecificAngularMomentum3D vector) => new() { X = -vector.X, Y = -vector.Y, Z = -vector.Z };
+};
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentumMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentumMagnitude.g.cs
new file mode 100644
index 00000000..28996b07
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificAngularMomentumMagnitude.g.cs
@@ -0,0 +1,119 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Magnitude (Vector0) quantity for the SpecificAngularMomentum dimension.
+///
+/// The numeric storage type.
+public readonly partial record struct SpecificAngularMomentumMagnitude : IVector0, T>, IPhysicalQuantity, T>
+ where T : struct, INumber
+{
+ /// Gets the value stored in this quantity (in the dimension's SI base unit).
+ public T Value => Quantity;
+
+ /// Gets whether this quantity is finite and not NaN.
+ public bool IsPhysicallyValid => PhysicalQuantityCore.IsPhysicallyValid(Quantity);
+
+ /// Gets a quantity with value zero.
+ public static SpecificAngularMomentumMagnitude Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public DimensionInfo Dimension => PhysicalDimensions.SpecificAngularMomentum;
+
+ /// Gets the stored value, in the dimension's SI base unit.
+ public T Quantity { get; init; }
+
+ ///
+ /// Creates a quantity holding , in the SI base unit.
+ ///
+ /// The value in the SI base unit.
+ /// A new quantity holding .
+ public static SpecificAngularMomentumMagnitude Create(T value) => new() { Quantity = value };
+
+ ///
+ /// Compares this quantity to another of the same physical dimension.
+ ///
+ /// The quantity to compare against.
+ /// A negative number, zero or a positive number as this sorts before, with, or after .
+ /// When the two do not share a dimension.
+ public int CompareTo(IPhysicalQuantity other) => PhysicalQuantityCore.Compare, T>(this, other);
+
+ ///
+ /// Reports whether this quantity shares a dimension and a value with .
+ ///
+ /// The quantity to compare against.
+ /// when both dimension and value match.
+ public bool Equals(IPhysicalQuantity other) => PhysicalQuantityCore.AreEqual, T>(this, other);
+
+ /// Adds two values.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificAngularMomentumMagnitude operator +(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => Create(left.Quantity + right.Quantity);
+
+ /// Negates a .
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificAngularMomentumMagnitude operator -(SpecificAngularMomentumMagnitude value) => Create(-value.Quantity);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificAngularMomentumMagnitude operator *(SpecificAngularMomentumMagnitude left, T right) => Create(left.Quantity * right);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificAngularMomentumMagnitude operator *(T left, SpecificAngularMomentumMagnitude right) => Create(left * right.Quantity);
+
+ /// Divides a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificAngularMomentumMagnitude operator /(SpecificAngularMomentumMagnitude left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(left.Quantity / right);
+
+ /// Divides one by another, giving the bare ratio.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static T operator /(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : left.Quantity / right.Quantity;
+
+ /// Reports whether the left value sorts before the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => left.Quantity < right.Quantity;
+
+ /// Reports whether the left value sorts before or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <=(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => left.Quantity <= right.Quantity;
+
+ /// Reports whether the left value sorts after the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => left.Quantity > right.Quantity;
+
+ /// Reports whether the left value sorts after or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >=(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => left.Quantity >= right.Quantity;
+
+ /// Returns the stored value as text.
+ /// The value in the SI base unit, rendered by .
+ public override string ToString() => Quantity.ToString() ?? string.Empty;
+
+ ///
+ /// Creates a new from a value in SquareMeterPerSecond.
+ ///
+ /// The value in SquareMeterPerSecond.
+ /// A new instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static SpecificAngularMomentumMagnitude FromSquareMeterPerSecond(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+
+ ///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-SpecificAngularMomentum unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.ISpecificAngularMomentumUnit unit) => unit.FromBase(Value);
+
+ ///
+ /// Subtracts two SpecificAngularMomentumMagnitude values, returning the absolute difference as a non-negative SpecificAngularMomentumMagnitude.
+ /// Magnitude subtraction stays a magnitude (per the unified-vector model).
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificAngularMomentumMagnitude operator -(SpecificAngularMomentumMagnitude left, SpecificAngularMomentumMagnitude right) => Create(T.Abs(left.Quantity - right.Quantity));
+}
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEnergy.g.cs
new file mode 100644
index 00000000..d1460d92
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEnergy.g.cs
@@ -0,0 +1,121 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Signed one-dimensional (Vector1) quantity for the SpecificEnergy dimension.
+///
+/// The numeric storage type.
+public readonly partial record struct SpecificEnergy : IVector1, T>, IPhysicalQuantity, T>
+ where T : struct, INumber
+{
+ /// Gets the value stored in this quantity (in the dimension's SI base unit).
+ public T Value => Quantity;
+
+ /// Gets whether this quantity is finite and not NaN.
+ public bool IsPhysicallyValid => PhysicalQuantityCore.IsPhysicallyValid(Quantity);
+
+ /// Gets a quantity with value zero.
+ public static SpecificEnergy Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public DimensionInfo Dimension => PhysicalDimensions.SpecificEnergy;
+
+ /// Gets the stored value, in the dimension's SI base unit.
+ public T Quantity { get; init; }
+
+ ///
+ /// Creates a quantity holding , in the SI base unit.
+ ///
+ /// The value in the SI base unit.
+ /// A new quantity holding .
+ public static SpecificEnergy Create(T value) => new() { Quantity = value };
+
+ ///
+ /// Compares this quantity to another of the same physical dimension.
+ ///
+ /// The quantity to compare against.
+ /// A negative number, zero or a positive number as this sorts before, with, or after .
+ /// When the two do not share a dimension.
+ public int CompareTo(IPhysicalQuantity other) => PhysicalQuantityCore.Compare, T>(this, other);
+
+ ///
+ /// Reports whether this quantity shares a dimension and a value with .
+ ///
+ /// The quantity to compare against.
+ /// when both dimension and value match.
+ public bool Equals(IPhysicalQuantity other) => PhysicalQuantityCore.AreEqual, T>(this, other);
+
+ /// Adds two values.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergy operator +(SpecificEnergy left, SpecificEnergy right) => Create(left.Quantity + right.Quantity);
+
+ /// Subtracts one from another.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergy operator -(SpecificEnergy left, SpecificEnergy right) => Create(left.Quantity - right.Quantity);
+
+ /// Negates a .
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergy operator -(SpecificEnergy value) => Create(-value.Quantity);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergy operator *(SpecificEnergy left, T right) => Create(left.Quantity * right);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergy operator *(T left, SpecificEnergy right) => Create(left * right.Quantity);
+
+ /// Divides a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergy operator /(SpecificEnergy left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(left.Quantity / right);
+
+ /// Divides one by another, giving the bare ratio.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static T operator /(SpecificEnergy left, SpecificEnergy right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : left.Quantity / right.Quantity;
+
+ /// Reports whether the left value sorts before the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <(SpecificEnergy left, SpecificEnergy right) => left.Quantity < right.Quantity;
+
+ /// Reports whether the left value sorts before or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <=(SpecificEnergy left, SpecificEnergy right) => left.Quantity <= right.Quantity;
+
+ /// Reports whether the left value sorts after the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >(SpecificEnergy left, SpecificEnergy right) => left.Quantity > right.Quantity;
+
+ /// Reports whether the left value sorts after or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >=(SpecificEnergy left, SpecificEnergy right) => left.Quantity >= right.Quantity;
+
+ /// Returns the stored value as text.
+ /// The value in the SI base unit, rendered by .
+ public override string ToString() => Quantity.ToString() ?? string.Empty;
+
+ ///
+ /// Creates a new from a value in JoulePerKilogram.
+ ///
+ /// The value in JoulePerKilogram.
+ /// A new instance.
+ public static SpecificEnergy FromJoulePerKilogram(T value) => Create(value);
+
+ ///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-SpecificEnergy unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.ISpecificEnergyUnit unit) => unit.FromBase(Value);
+
+ ///
+ /// Gets the magnitude of this quantity as a .
+ ///
+ /// The non-negative magnitude.
+ public SpecificEnergyMagnitude Magnitude() => SpecificEnergyMagnitude.Create(T.Abs(Value));
+}
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEnergyMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEnergyMagnitude.g.cs
new file mode 100644
index 00000000..ab34e4b5
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificEnergyMagnitude.g.cs
@@ -0,0 +1,125 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Magnitude (Vector0) quantity for the SpecificEnergy dimension.
+///
+/// The numeric storage type.
+public readonly partial record struct SpecificEnergyMagnitude : IVector0, T>, IPhysicalQuantity, T>
+ where T : struct, INumber
+{
+ /// Gets the value stored in this quantity (in the dimension's SI base unit).
+ public T Value => Quantity;
+
+ /// Gets whether this quantity is finite and not NaN.
+ public bool IsPhysicallyValid => PhysicalQuantityCore.IsPhysicallyValid(Quantity);
+
+ /// Gets a quantity with value zero.
+ public static SpecificEnergyMagnitude Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public DimensionInfo Dimension => PhysicalDimensions.SpecificEnergy;
+
+ /// Gets the stored value, in the dimension's SI base unit.
+ public T Quantity { get; init; }
+
+ ///
+ /// Creates a quantity holding , in the SI base unit.
+ ///
+ /// The value in the SI base unit.
+ /// A new quantity holding .
+ public static SpecificEnergyMagnitude Create(T value) => new() { Quantity = value };
+
+ ///
+ /// Compares this quantity to another of the same physical dimension.
+ ///
+ /// The quantity to compare against.
+ /// A negative number, zero or a positive number as this sorts before, with, or after .
+ /// When the two do not share a dimension.
+ public int CompareTo(IPhysicalQuantity other) => PhysicalQuantityCore.Compare, T>(this, other);
+
+ ///
+ /// Reports whether this quantity shares a dimension and a value with .
+ ///
+ /// The quantity to compare against.
+ /// when both dimension and value match.
+ public bool Equals(IPhysicalQuantity other) => PhysicalQuantityCore.AreEqual, T>(this, other);
+
+ /// Adds two values.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator +(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => Create(left.Quantity + right.Quantity);
+
+ /// Negates a .
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator -(SpecificEnergyMagnitude value) => Create(-value.Quantity);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator *(SpecificEnergyMagnitude left, T right) => Create(left.Quantity * right);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator *(T left, SpecificEnergyMagnitude right) => Create(left * right.Quantity);
+
+ /// Divides a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator /(SpecificEnergyMagnitude left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(left.Quantity / right);
+
+ /// Divides one by another, giving the bare ratio.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static T operator /(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : left.Quantity / right.Quantity;
+
+ /// Reports whether the left value sorts before the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => left.Quantity < right.Quantity;
+
+ /// Reports whether the left value sorts before or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <=(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => left.Quantity <= right.Quantity;
+
+ /// Reports whether the left value sorts after the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => left.Quantity > right.Quantity;
+
+ /// Reports whether the left value sorts after or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >=(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => left.Quantity >= right.Quantity;
+
+ /// Returns the stored value as text.
+ /// The value in the SI base unit, rendered by .
+ public override string ToString() => Quantity.ToString() ?? string.Empty;
+
+ ///
+ /// Creates a new from a value in JoulePerKilogram.
+ ///
+ /// The value in JoulePerKilogram.
+ /// A new instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static SpecificEnergyMagnitude FromJoulePerKilogram(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+
+ ///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-SpecificEnergy unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.ISpecificEnergyUnit unit) => unit.FromBase(Value);
+
+ ///
+ /// Subtracts two SpecificEnergyMagnitude values, returning the absolute difference as a non-negative SpecificEnergyMagnitude.
+ /// Magnitude subtraction stays a magnitude (per the unified-vector model).
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificEnergyMagnitude operator -(SpecificEnergyMagnitude left, SpecificEnergyMagnitude right) => Create(T.Abs(left.Quantity - right.Quantity));
+
+ ///
+ /// Multiplies SpecificEnergyMagnitude by Length to produce GravitationalParameter.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static GravitationalParameter operator *(SpecificEnergyMagnitude left, Length right) => GravitationalParameter.Create(left.Quantity * right.Quantity);
+}
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs
new file mode 100644
index 00000000..b3dbc35a
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificKineticEnergy.g.cs
@@ -0,0 +1,126 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Kinetic energy per unit mass, which is never negative.
+/// Semantic overload of .
+///
+/// The numeric storage type.
+public readonly partial record struct SpecificKineticEnergy : IVector0, T>, IPhysicalQuantity, T>
+ where T : struct, INumber
+{
+ /// Gets the value stored in this quantity (in the dimension's SI base unit).
+ public T Value => Quantity;
+
+ /// Gets whether this quantity is finite and not NaN.
+ public bool IsPhysicallyValid => PhysicalQuantityCore.IsPhysicallyValid(Quantity);
+
+ /// Gets a quantity with value zero.
+ public static SpecificKineticEnergy Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public DimensionInfo Dimension => PhysicalDimensions.SpecificEnergy;
+
+ /// Gets the stored value, in the dimension's SI base unit.
+ public T Quantity { get; init; }
+
+ ///
+ /// Creates a quantity holding , in the SI base unit.
+ ///
+ /// The value in the SI base unit.
+ /// A new quantity holding .
+ public static SpecificKineticEnergy Create(T value) => new() { Quantity = value };
+
+ ///
+ /// Compares this quantity to another of the same physical dimension.
+ ///
+ /// The quantity to compare against.
+ /// A negative number, zero or a positive number as this sorts before, with, or after .
+ /// When the two do not share a dimension.
+ public int CompareTo(IPhysicalQuantity other) => PhysicalQuantityCore.Compare, T>(this, other);
+
+ ///
+ /// Reports whether this quantity shares a dimension and a value with .
+ ///
+ /// The quantity to compare against.
+ /// when both dimension and value match.
+ public bool Equals(IPhysicalQuantity other) => PhysicalQuantityCore.AreEqual, T>(this, other);
+
+ /// Adds two values.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificKineticEnergy operator +(SpecificKineticEnergy left, SpecificKineticEnergy right) => Create(left.Quantity + right.Quantity);
+
+ /// Negates a .
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificKineticEnergy operator -(SpecificKineticEnergy value) => Create(-value.Quantity);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificKineticEnergy operator *(SpecificKineticEnergy left, T right) => Create(left.Quantity * right);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificKineticEnergy operator *(T left, SpecificKineticEnergy right) => Create(left * right.Quantity);
+
+ /// Divides a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificKineticEnergy operator /(SpecificKineticEnergy left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(left.Quantity / right);
+
+ /// Divides one by another, giving the bare ratio.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static T operator /(SpecificKineticEnergy left, SpecificKineticEnergy right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : left.Quantity / right.Quantity;
+
+ /// Reports whether the left value sorts before the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <(SpecificKineticEnergy left, SpecificKineticEnergy right) => left.Quantity < right.Quantity;
+
+ /// Reports whether the left value sorts before or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <=(SpecificKineticEnergy left, SpecificKineticEnergy right) => left.Quantity <= right.Quantity;
+
+ /// Reports whether the left value sorts after the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >(SpecificKineticEnergy left, SpecificKineticEnergy right) => left.Quantity > right.Quantity;
+
+ /// Reports whether the left value sorts after or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >=(SpecificKineticEnergy left, SpecificKineticEnergy right) => left.Quantity >= right.Quantity;
+
+ /// Returns the stored value as text.
+ /// The value in the SI base unit, rendered by .
+ public override string ToString() => Quantity.ToString() ?? string.Empty;
+
+ ///
+ /// Creates a new SpecificKineticEnergy from a value in JoulePerKilogram.
+ ///
+ /// The value in JoulePerKilogram.
+ /// A new SpecificKineticEnergy instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static SpecificKineticEnergy FromJoulePerKilogram(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+
+ ///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-SpecificEnergy unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.ISpecificEnergyUnit unit) => unit.FromBase(Value);
+
+ /// Implicit conversion to SpecificEnergyMagnitude.
+ public static implicit operator SpecificEnergyMagnitude(SpecificKineticEnergy value) => SpecificEnergyMagnitude.Create(value.Value);
+
+ /// Explicit conversion from SpecificEnergyMagnitude.
+ public static explicit operator SpecificKineticEnergy(SpecificEnergyMagnitude value) => Create(value.Value);
+
+ /// Creates a SpecificKineticEnergy from a SpecificEnergyMagnitude value.
+ public static SpecificKineticEnergy From(SpecificEnergyMagnitude value) => Create(value.Value);
+
+ /// Subtracts two SpecificKineticEnergy values, returning the absolute difference as a non-negative SpecificKineticEnergy.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificKineticEnergy operator -(SpecificKineticEnergy left, SpecificKineticEnergy right) => Create(T.Abs(left.Quantity - right.Quantity));
+}
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificOrbitalEnergy.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificOrbitalEnergy.g.cs
new file mode 100644
index 00000000..f711c707
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/SpecificOrbitalEnergy.g.cs
@@ -0,0 +1,125 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Orbital energy per unit reduced mass, negative for every bound orbit.
+/// Semantic overload of .
+///
+/// The numeric storage type.
+public readonly partial record struct SpecificOrbitalEnergy : IVector1, T>, IPhysicalQuantity, T>
+ where T : struct, INumber
+{
+ /// Gets the value stored in this quantity (in the dimension's SI base unit).
+ public T Value => Quantity;
+
+ /// Gets whether this quantity is finite and not NaN.
+ public bool IsPhysicallyValid => PhysicalQuantityCore.IsPhysicallyValid(Quantity);
+
+ /// Gets a quantity with value zero.
+ public static SpecificOrbitalEnergy Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public DimensionInfo Dimension => PhysicalDimensions.SpecificEnergy;
+
+ /// Gets the stored value, in the dimension's SI base unit.
+ public T Quantity { get; init; }
+
+ ///
+ /// Creates a quantity holding , in the SI base unit.
+ ///
+ /// The value in the SI base unit.
+ /// A new quantity holding .
+ public static SpecificOrbitalEnergy Create(T value) => new() { Quantity = value };
+
+ ///
+ /// Compares this quantity to another of the same physical dimension.
+ ///
+ /// The quantity to compare against.
+ /// A negative number, zero or a positive number as this sorts before, with, or after .
+ /// When the two do not share a dimension.
+ public int CompareTo(IPhysicalQuantity other) => PhysicalQuantityCore.Compare, T>(this, other);
+
+ ///
+ /// Reports whether this quantity shares a dimension and a value with .
+ ///
+ /// The quantity to compare against.
+ /// when both dimension and value match.
+ public bool Equals(IPhysicalQuantity other) => PhysicalQuantityCore.AreEqual, T>(this, other);
+
+ /// Adds two values.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificOrbitalEnergy operator +(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => Create(left.Quantity + right.Quantity);
+
+ /// Subtracts one from another.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificOrbitalEnergy operator -(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => Create(left.Quantity - right.Quantity);
+
+ /// Negates a .
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificOrbitalEnergy operator -(SpecificOrbitalEnergy value) => Create(-value.Quantity);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificOrbitalEnergy operator *(SpecificOrbitalEnergy left, T right) => Create(left.Quantity * right);
+
+ /// Scales a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificOrbitalEnergy operator *(T left, SpecificOrbitalEnergy right) => Create(left * right.Quantity);
+
+ /// Divides a by a bare number.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static SpecificOrbitalEnergy operator /(SpecificOrbitalEnergy left, T right) => T.IsZero(right) ? throw new System.DivideByZeroException("Cannot divide by zero.") : Create(left.Quantity / right);
+
+ /// Divides one by another, giving the bare ratio.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static T operator /(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => T.IsZero(right.Quantity) ? throw new System.DivideByZeroException("Cannot divide by zero.") : left.Quantity / right.Quantity;
+
+ /// Reports whether the left value sorts before the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => left.Quantity < right.Quantity;
+
+ /// Reports whether the left value sorts before or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator <=(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => left.Quantity <= right.Quantity;
+
+ /// Reports whether the left value sorts after the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => left.Quantity > right.Quantity;
+
+ /// Reports whether the left value sorts after or with the right.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")]
+ public static bool operator >=(SpecificOrbitalEnergy left, SpecificOrbitalEnergy right) => left.Quantity >= right.Quantity;
+
+ /// Returns the stored value as text.
+ /// The value in the SI base unit, rendered by .
+ public override string ToString() => Quantity.ToString() ?? string.Empty;
+
+ ///
+ /// Creates a new SpecificOrbitalEnergy from a value in JoulePerKilogram.
+ ///
+ /// The value in JoulePerKilogram.
+ /// A new SpecificOrbitalEnergy instance.
+ public static SpecificOrbitalEnergy FromJoulePerKilogram(T value) => Create(value);
+
+ ///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-SpecificEnergy unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.ISpecificEnergyUnit unit) => unit.FromBase(Value);
+
+ /// Implicit conversion to SpecificEnergy.
+ public static implicit operator SpecificEnergy(SpecificOrbitalEnergy value) => SpecificEnergy