Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<Using Include="ktsu.Semantics.Quantities.GaugePressure&lt;decimal&gt;" Alias="GaugePressure" />
<Using Include="ktsu.Semantics.Quantities.GravitationalAcceleration&lt;decimal&gt;" Alias="GravitationalAcceleration" />
<Using Include="ktsu.Semantics.Quantities.GravitationalField3D&lt;decimal&gt;" Alias="GravitationalField3D" />
<Using Include="ktsu.Semantics.Quantities.GravitationalParameter&lt;decimal&gt;" Alias="GravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.GroundSpeed&lt;decimal&gt;" Alias="GroundSpeed" />
<Using Include="ktsu.Semantics.Quantities.GroupVelocity&lt;decimal&gt;" Alias="GroupVelocity" />
<Using Include="ktsu.Semantics.Quantities.HalfLife&lt;decimal&gt;" Alias="HalfLife" />
Expand Down Expand Up @@ -180,10 +181,17 @@
<Using Include="ktsu.Semantics.Quantities.SoundPressureLevel&lt;decimal&gt;" Alias="SoundPressureLevel" />
<Using Include="ktsu.Semantics.Quantities.SoundSpeed&lt;decimal&gt;" Alias="SoundSpeed" />
<Using Include="ktsu.Semantics.Quantities.SoundTransmissionClass&lt;decimal&gt;" Alias="SoundTransmissionClass" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentum3D&lt;decimal&gt;" Alias="SpecificAngularMomentum3D" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude&lt;decimal&gt;" Alias="SpecificAngularMomentumMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergy&lt;decimal&gt;" Alias="SpecificEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergyMagnitude&lt;decimal&gt;" Alias="SpecificEnergyMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEntropy&lt;decimal&gt;" Alias="SpecificEntropy" />
<Using Include="ktsu.Semantics.Quantities.SpecificGravity&lt;decimal&gt;" Alias="SpecificGravity" />
<Using Include="ktsu.Semantics.Quantities.SpecificHeat&lt;decimal&gt;" Alias="SpecificHeat" />
<Using Include="ktsu.Semantics.Quantities.SpecificKineticEnergy&lt;decimal&gt;" Alias="SpecificKineticEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificOrbitalEnergy&lt;decimal&gt;" Alias="SpecificOrbitalEnergy" />
<Using Include="ktsu.Semantics.Quantities.Speed&lt;decimal&gt;" Alias="Speed" />
<Using Include="ktsu.Semantics.Quantities.StandardGravitationalParameter&lt;decimal&gt;" Alias="StandardGravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.Stress&lt;decimal&gt;" Alias="Stress" />
<Using Include="ktsu.Semantics.Quantities.SurfaceArea&lt;decimal&gt;" Alias="SurfaceArea" />
<Using Include="ktsu.Semantics.Quantities.SurfaceTension&lt;decimal&gt;" Alias="SurfaceTension" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<Using Include="ktsu.Semantics.Quantities.GaugePressure&lt;double&gt;" Alias="GaugePressure" />
<Using Include="ktsu.Semantics.Quantities.GravitationalAcceleration&lt;double&gt;" Alias="GravitationalAcceleration" />
<Using Include="ktsu.Semantics.Quantities.GravitationalField3D&lt;double&gt;" Alias="GravitationalField3D" />
<Using Include="ktsu.Semantics.Quantities.GravitationalParameter&lt;double&gt;" Alias="GravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.GroundSpeed&lt;double&gt;" Alias="GroundSpeed" />
<Using Include="ktsu.Semantics.Quantities.GroupVelocity&lt;double&gt;" Alias="GroupVelocity" />
<Using Include="ktsu.Semantics.Quantities.HalfLife&lt;double&gt;" Alias="HalfLife" />
Expand Down Expand Up @@ -180,10 +181,17 @@
<Using Include="ktsu.Semantics.Quantities.SoundPressureLevel&lt;double&gt;" Alias="SoundPressureLevel" />
<Using Include="ktsu.Semantics.Quantities.SoundSpeed&lt;double&gt;" Alias="SoundSpeed" />
<Using Include="ktsu.Semantics.Quantities.SoundTransmissionClass&lt;double&gt;" Alias="SoundTransmissionClass" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentum3D&lt;double&gt;" Alias="SpecificAngularMomentum3D" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude&lt;double&gt;" Alias="SpecificAngularMomentumMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergy&lt;double&gt;" Alias="SpecificEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergyMagnitude&lt;double&gt;" Alias="SpecificEnergyMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEntropy&lt;double&gt;" Alias="SpecificEntropy" />
<Using Include="ktsu.Semantics.Quantities.SpecificGravity&lt;double&gt;" Alias="SpecificGravity" />
<Using Include="ktsu.Semantics.Quantities.SpecificHeat&lt;double&gt;" Alias="SpecificHeat" />
<Using Include="ktsu.Semantics.Quantities.SpecificKineticEnergy&lt;double&gt;" Alias="SpecificKineticEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificOrbitalEnergy&lt;double&gt;" Alias="SpecificOrbitalEnergy" />
<Using Include="ktsu.Semantics.Quantities.Speed&lt;double&gt;" Alias="Speed" />
<Using Include="ktsu.Semantics.Quantities.StandardGravitationalParameter&lt;double&gt;" Alias="StandardGravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.Stress&lt;double&gt;" Alias="Stress" />
<Using Include="ktsu.Semantics.Quantities.SurfaceArea&lt;double&gt;" Alias="SurfaceArea" />
<Using Include="ktsu.Semantics.Quantities.SurfaceTension&lt;double&gt;" Alias="SurfaceTension" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<Using Include="ktsu.Semantics.Quantities.GaugePressure&lt;float&gt;" Alias="GaugePressure" />
<Using Include="ktsu.Semantics.Quantities.GravitationalAcceleration&lt;float&gt;" Alias="GravitationalAcceleration" />
<Using Include="ktsu.Semantics.Quantities.GravitationalField3D&lt;float&gt;" Alias="GravitationalField3D" />
<Using Include="ktsu.Semantics.Quantities.GravitationalParameter&lt;float&gt;" Alias="GravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.GroundSpeed&lt;float&gt;" Alias="GroundSpeed" />
<Using Include="ktsu.Semantics.Quantities.GroupVelocity&lt;float&gt;" Alias="GroupVelocity" />
<Using Include="ktsu.Semantics.Quantities.HalfLife&lt;float&gt;" Alias="HalfLife" />
Expand Down Expand Up @@ -180,10 +181,17 @@
<Using Include="ktsu.Semantics.Quantities.SoundPressureLevel&lt;float&gt;" Alias="SoundPressureLevel" />
<Using Include="ktsu.Semantics.Quantities.SoundSpeed&lt;float&gt;" Alias="SoundSpeed" />
<Using Include="ktsu.Semantics.Quantities.SoundTransmissionClass&lt;float&gt;" Alias="SoundTransmissionClass" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentum3D&lt;float&gt;" Alias="SpecificAngularMomentum3D" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude&lt;float&gt;" Alias="SpecificAngularMomentumMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergy&lt;float&gt;" Alias="SpecificEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergyMagnitude&lt;float&gt;" Alias="SpecificEnergyMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEntropy&lt;float&gt;" Alias="SpecificEntropy" />
<Using Include="ktsu.Semantics.Quantities.SpecificGravity&lt;float&gt;" Alias="SpecificGravity" />
<Using Include="ktsu.Semantics.Quantities.SpecificHeat&lt;float&gt;" Alias="SpecificHeat" />
<Using Include="ktsu.Semantics.Quantities.SpecificKineticEnergy&lt;float&gt;" Alias="SpecificKineticEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificOrbitalEnergy&lt;float&gt;" Alias="SpecificOrbitalEnergy" />
<Using Include="ktsu.Semantics.Quantities.Speed&lt;float&gt;" Alias="Speed" />
<Using Include="ktsu.Semantics.Quantities.StandardGravitationalParameter&lt;float&gt;" Alias="StandardGravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.Stress&lt;float&gt;" Alias="Stress" />
<Using Include="ktsu.Semantics.Quantities.SurfaceArea&lt;float&gt;" Alias="SurfaceArea" />
<Using Include="ktsu.Semantics.Quantities.SurfaceTension&lt;float&gt;" Alias="SurfaceTension" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
<Using Include="ktsu.Semantics.Quantities.GaugePressure&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="GaugePressure" />
<Using Include="ktsu.Semantics.Quantities.GravitationalAcceleration&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="GravitationalAcceleration" />
<Using Include="ktsu.Semantics.Quantities.GravitationalField3D&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="GravitationalField3D" />
<Using Include="ktsu.Semantics.Quantities.GravitationalParameter&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="GravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.GroundSpeed&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="GroundSpeed" />
<Using Include="ktsu.Semantics.Quantities.GroupVelocity&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="GroupVelocity" />
<Using Include="ktsu.Semantics.Quantities.HalfLife&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="HalfLife" />
Expand Down Expand Up @@ -180,10 +181,17 @@
<Using Include="ktsu.Semantics.Quantities.SoundPressureLevel&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SoundPressureLevel" />
<Using Include="ktsu.Semantics.Quantities.SoundSpeed&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SoundSpeed" />
<Using Include="ktsu.Semantics.Quantities.SoundTransmissionClass&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SoundTransmissionClass" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentum3D&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificAngularMomentum3D" />
<Using Include="ktsu.Semantics.Quantities.SpecificAngularMomentumMagnitude&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificAngularMomentumMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergy&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificEnergyMagnitude&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificEnergyMagnitude" />
<Using Include="ktsu.Semantics.Quantities.SpecificEntropy&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificEntropy" />
<Using Include="ktsu.Semantics.Quantities.SpecificGravity&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificGravity" />
<Using Include="ktsu.Semantics.Quantities.SpecificHeat&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificHeat" />
<Using Include="ktsu.Semantics.Quantities.SpecificKineticEnergy&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificKineticEnergy" />
<Using Include="ktsu.Semantics.Quantities.SpecificOrbitalEnergy&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SpecificOrbitalEnergy" />
<Using Include="ktsu.Semantics.Quantities.Speed&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="Speed" />
<Using Include="ktsu.Semantics.Quantities.StandardGravitationalParameter&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="StandardGravitationalParameter" />
<Using Include="ktsu.Semantics.Quantities.Stress&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="Stress" />
<Using Include="ktsu.Semantics.Quantities.SurfaceArea&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SurfaceArea" />
<Using Include="ktsu.Semantics.Quantities.SurfaceTension&lt;ktsu.PreciseNumber.PreciseNumber&gt;" Alias="SurfaceTension" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ internal static class ConversionConstants
/// <summary>Standard gravity to meters per second squared: 9.80665 m/s² per g (exact by definition)</summary>
internal const double StandardGravityToMeterPerSecondSquared = 9.80665d;

/// <summary>Cubic kilometer per second squared to cubic meter per second squared: 1e9 m³/s² per km³/s² (exact by definition)</summary>
internal const double CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared = 1e9d;

/// <summary>Dyne to newton conversion: 1e-5 N/dyn (exact by definition)</summary>
internal const double DyneToNewtons = 1e-5d;

Expand Down Expand Up @@ -737,6 +740,12 @@ internal static class Values<T>
/// <summary>StandardGravityToMeterPerSecondSquared parsed into <typeparamref name="T"/>, or <see langword="null"/> when the <see langword="double"/> is converted at each read.</summary>
private static readonly T? ParsedStandardGravityToMeterPerSecondSquared = StorageLiteral.Parse<T>("9.80665");

/// <summary>Cubic kilometer per second squared to cubic meter per second squared: 1e9 m³/s² per km³/s² (exact by definition)</summary>
internal static T CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared => ParsedCubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared ?? T.CreateChecked(ConversionConstants.CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared);

/// <summary>CubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared parsed into <typeparamref name="T"/>, or <see langword="null"/> when the <see langword="double"/> is converted at each read.</summary>
private static readonly T? ParsedCubicKilometerPerSecondSquaredToCubicMeterPerSecondSquared = StorageLiteral.Parse<T>("1e9");

/// <summary>Dyne to newton conversion: 1e-5 N/dyn (exact by definition)</summary>
internal static T DyneToNewtons => ParsedDyneToNewtons ?? T.CreateChecked(ConversionConstants.DyneToNewtons);

Expand Down
Loading
Loading