From ba9d770cfcb508ada0526c7dd646ff3d94e97baa Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 10 May 2026 13:38:48 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20fix=20stale=20README=20+=20guides=20?= =?UTF-8?q?=E2=80=94=20plural=20factories,=20V3=20object-init,=20real=20Ph?= =?UTF-8?q?ysicalConstants=20surface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sweeps three user-facing docs to match the current generator output: README.md - V0 factory examples already correct on plural (FromMetersPerSecond, FromMeters, FromKilograms, FromNewtons, FromSeconds). - V3 examples (Force3D, Displacement3D) switched from non-existent 3-arg From{Unit}(x, y, z) factories to object-initializer construction with X/Y/Z components, which matches what the generator actually emits. - Magnitude() example now says "Length" rather than "Distance" — the V3 base's Magnitude() returns the V0 base of the dimension, not an overload. - Added a comment showing the construction-time invariants from #50/#51 (Speed.FromMetersPerSecond(-1) and Wavelength.FromMeters(0) both throw ArgumentException). - Removed the aspirational PhysicalConstants.Conversion.X() examples (CLAUDE.md was already cleaned up in #70 but README hadn't been). Replaced with the real domain-grouped / Generic() shape that PhysicalConstantsGenerator emits today. - Architecture section: now lists units.json/magnitudes.json/ conversions.json/domains.json alongside dimensions.json and adds the SEM001/SEM002/SEM003 diagnostic line-up. docs/physics-domains-guide.md - Magnitude / Cross / Dot examples use object-initializer for V3, matching the generated surface. docs/complete-library-guide.md - Same V3 fix. - "mass * Acceleration.FromMeters(9.8)" was nonsense on two counts (Acceleration is a dimension name, not a generated type; Meters is the wrong unit for acceleration). Replaced with the correct AccelerationMagnitude.FromMetersPerSecondSquared(9.8). - Magnitude() example now says "Length" rather than "Distance"; same reason as the README fix. No code or generated output changes; pure docs sync to current API. --- README.md | 54 +++++++++++++++++++++------------- docs/complete-library-guide.md | 18 ++++++------ docs/physics-domains-guide.md | 14 +++++---- 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 0734322..588a93d 100644 --- a/README.md +++ b/README.md @@ -99,45 +99,53 @@ Every quantity is a vector. Direction-space dimensionality is part of the type: ```csharp using ktsu.Semantics.Quantities; -// V0 magnitudes +// V0 magnitudes — From{Unit} factories use the plural form (#49) var speed = Speed.FromMetersPerSecond(15.0); -var mass = Mass.FromKilogram(10.0); -var distance = Distance.FromMeter(5.0); +var mass = Mass.FromKilograms(10.0); +var distance = Distance.FromMeters(5.0); -// V3 directional -var force3d = Force3D.FromNewton(0.0, 0.0, -9.8); -var disp3d = Displacement3D.FromMeter(3.0, 4.0, 0.0); +// V3 directional — object-initializer syntax (X/Y/Z components) +var force3d = new Force3D { X = 0.0, Y = 0.0, Z = -9.8 }; +var disp3d = new Displacement3D { X = 3.0, Y = 4.0, Z = 0.0 }; // Operators flow from dimensions.json -var work = ForceMagnitude.FromNewton(10.0) * distance; // F·d = Energy -var power = work / Duration.FromSecond(2.0); // W/t = Power +var work = ForceMagnitude.FromNewtons(10.0) * distance; // F·d = Energy +var power = work / Duration.FromSeconds(2.0); // W/t = Power // Vector ops var workDot = force3d.Dot(disp3d); // Energy var torque = force3d.Cross(disp3d); // Torque3D -var mag = disp3d.Magnitude(); // Distance (always >= 0) +var mag = disp3d.Magnitude(); // Length (always >= 0) + +// Construction-time invariants (#50, #51) +// Speed.FromMetersPerSecond(-1.0) // ArgumentException — V0 must be non-negative +// Wavelength.FromMeters(0.0) // ArgumentException — strict-positive overload // Type safety -// var nope = force3d + speed; // ❌ compiler error +// var nope = force3d + speed; // ❌ compiler error ``` Semantic overloads (e.g. `Weight` over `ForceMagnitude`, `Diameter` ↔ `Radius`): ```csharp -var raw = ForceMagnitude.FromNewton(686.0); +var raw = ForceMagnitude.FromNewtons(686.0); var weight = Weight.From(raw); // explicit narrow ForceMagnitude back = weight; // implicit widen -var radius = Radius.FromMeter(2.0); +var radius = Radius.FromMeters(2.0); var diameter = radius.ToDiameter(); // 4 m via metadata-defined relationship ``` -Physical constants: +Physical constants are exposed in two shapes: ```csharp -var c = PhysicalConstants.Generic.SpeedOfLight(); // 299_792_458 m/s -var R = PhysicalConstants.Generic.GasConstant(); -var ftM = PhysicalConstants.Conversion.FeetToMeters(); // 0.3048 +// Domain-grouped, exact PreciseNumber values: +PhysicalConstants.Fundamental.SpeedOfLight; // 299_792_458 m/s as PreciseNumber +PhysicalConstants.Chemistry.GasConstant; // 8.31446... J/(mol·K) + +// Generic accessors — materialise into any T : INumber: +var c = PhysicalConstants.Generic.SpeedOfLight(); +var R = PhysicalConstants.Generic.GasConstant(); ``` The unified vector model and its rationale: [`docs/strategy-unified-vector-quantities.md`](docs/strategy-unified-vector-quantities.md). @@ -161,12 +169,18 @@ public class UserService(ISemanticStringFactory emails) ## Architecture The physics system is **metadata-driven**. The single source of truth is -`Semantics.SourceGenerators/Metadata/dimensions.json`, with a Roslyn incremental generator emitting: +`Semantics.SourceGenerators/Metadata/dimensions.json` (with `units.json`, `magnitudes.json`, `conversions.json`, and `domains.json` alongside it), and a Roslyn incremental generator emits: - One record per quantity (Vector0/1/2/3/4 base + semantic overloads). -- `From{Unit}` factories. -- Cross-dimensional `*`, `/`, `Dot`, `Cross` operators. -- `PhysicalConstants.Generic.X()` and `PhysicalConstants.Conversion.X()`. +- A `From{Unit}` factory per declared unit, with built-in unit conversion to the SI base unit and a `Vector0Guards` enforce-non-negative (or strict-positive) check on V0 types. +- Cross-dimensional `*`, `/`, `Dot`, `Cross` operators driven by `integrals` / `derivatives` / `dotProducts` / `crossProducts` declarations. +- `PhysicalConstants` with both domain-grouped `PreciseNumber` fields and generic `T.CreateChecked`-backed accessors. + +Generator diagnostics catch metadata problems at build time: + +- **SEM001** — relationship references an unknown dimension name. +- **SEM002** — schema-level metadata issue (missing fields, duplicate type names, etc). +- **SEM003** — relationship's `forms` list references a vector form not declared on a participating dimension. Generated output is committed to `Semantics.Quantities/Generated/` so the project compiles without first running the generator. diff --git a/docs/complete-library-guide.md b/docs/complete-library-guide.md index 6a8f474..6dd8ac6 100644 --- a/docs/complete-library-guide.md +++ b/docs/complete-library-guide.md @@ -152,9 +152,9 @@ var energy = Energy.FromJoules(1_000.0); var v1 = Velocity1D.FromMetersPerSecond(-3.5); var temp = Temperature.FromKelvins(300.0); -// Vector3 — directional -var force3d = Force3D.FromNewtons(0.0, 0.0, -9.8); -var disp3d = Displacement3D.FromMeters(3.0, 4.0, 0.0); +// Vector3 — directional (object-initializer with X/Y/Z components) +var force3d = new Force3D { X = 0.0, Y = 0.0, Z = -9.8 }; +var disp3d = new Displacement3D { X = 3.0, Y = 4.0, Z = 0.0 }; ``` ### Operators and dimensional analysis @@ -163,14 +163,14 @@ Cross-dimensional operators are declared in `dimensions.json` and emitted automa ```csharp // V0 × V0 (magnitudes) -var force = mass * Acceleration.FromMeters(9.8); // Mass × Accel = Force -var work = ForceMagnitude.FromNewtons(10.0) * distance; // F·d = Energy -var power = work / Duration.FromSeconds(2.0); // W/t = Power +var force = mass * AccelerationMagnitude.FromMetersPerSecondSquared(9.8); // Mass × Accel = Force +var work = ForceMagnitude.FromNewtons(10.0) * distance; // F·d = Energy +var power = work / Duration.FromSeconds(2.0); // W/t = Power // Vector ops -var workScalar = force3d.Dot(disp3d); // Energy -var torque = force3d.Cross(disp3d); // Torque3D -var magnitude = disp3d.Magnitude(); // Distance +var workScalar = force3d.Dot(disp3d); // Energy (V0) +var torque = force3d.Cross(disp3d); // Torque3D (V3) +var magnitude = disp3d.Magnitude(); // Length (V0, always >= 0) // Type safety // var nope = force + temp; // ❌ compiler error diff --git a/docs/physics-domains-guide.md b/docs/physics-domains-guide.md index 5e1a381..79daaf1 100644 --- a/docs/physics-domains-guide.md +++ b/docs/physics-domains-guide.md @@ -43,7 +43,8 @@ var temp = Temperature.FromKelvins(298.15); - `Frequency` — V0 with overloads `SamplingRate`, `BitRate`, `RefreshRate`, `RotationalSpeed`. ```csharp -var velocity3d = Velocity3D.FromMetersPerSecond(3.0, 4.0, 0.0); +// V3 vectors use object-initializer construction (X / Y / Z components) +var velocity3d = new Velocity3D { X = 3.0, Y = 4.0, Z = 0.0 }; var speed = velocity3d.Magnitude(); // 5.0 (Speed) var sampling = SamplingRate.FromHertz(48_000); ``` @@ -165,23 +166,24 @@ var M = n / V; // Concentration v = Velocity3D.FromMetersPerSecond(3.0, 4.0, 0.0); +Velocity3D v = new() { X = 3.0, Y = 4.0, Z = 0.0 }; Speed s = v.Magnitude(); // 5.0, always >= 0 ``` ### Cross product (V3 only) ```csharp -Force3D F = Force3D.FromNewtons(0.0, 10.0, 0.0); -Displacement3D r = Displacement3D.FromMeters(0.5, 0.0, 0.0); +Force3D F = new() { X = 0.0, Y = 10.0, Z = 0.0 }; +Displacement3D r = new() { X = 0.5, Y = 0.0, Z = 0.0 }; Torque3D τ = F.Cross(r); ``` ### Dot product ```csharp -Energy work = Force3D.FromNewtons(10.0, 0.0, 0.0) - .Dot(Displacement3D.FromMeters(2.0, 0.0, 0.0)); // 20 J +Force3D F = new() { X = 10.0, Y = 0.0, Z = 0.0 }; +Displacement3D r = new() { X = 2.0, Y = 0.0, Z = 0.0 }; +Energy work = F.Dot(r); // 20 J ``` ### Semantic overload narrowing