Skip to content

[minor] Keep Vector0 magnitudes non-negative through unary minus and scalar * and / - #343

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/vector0-negation-and-scaling
Sep 30, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/vector0-negation-and-scaling

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #285

What was wrong

The generator already withheld binary - from V0 forms. It still emitted unary - and unguarded scalar * and /, so a single operator could take a magnitude below zero:

  • -Temperature<double>.FromKelvin(300) → −300 K
  • Speed<double>.FromMeterPerSecond(2) * -3.0 → −6 m/s

Change (QuantitiesGenerator.AddValueTypeCore)

  • V0 forms, bases and overloads alike, no longer declare unary operator -. That matches how binary - is already handled.
  • A V0's scalar operator *(q, T), operator *(T, q) and operator /(q, T) now pass the result through Vector0Guards.EnsureNonNegative, so a negative scalar throws ArgumentException. Divide-by-zero still throws DivideByZeroException as before.
  • V1 forms are unchanged: they are signed, keep negation, and scale by any sign.
  • docs/complete-library-guide.md claimed that Speed.Create(-1) throws. It doesn't: Create is the unguarded primitive. The guide now points at the guarded factory and the operator rules.
  • The regenerated output in Semantics.Quantities/Generated makes up most of the 156-file diff: one hunk per V0 type.

Breaking: code that negates a V0 quantity no longer compiles, and scaling a V0 by a negative number now throws. Hence [minor].

Tests

  • Vector0InvariantTests gains 7 tests:
    • V0 types (Temperature, Speed, Distance) have no op_UnaryNegation.
    • V0 * and / by a negative scalar throw, on both a base and an overload.
    • Non-negative scaling and zero still work.
    • V1 negation and negative scaling are unchanged.
  • I reverted the generator and generated files and re-ran the suite: the 4 V0 assertions fail. With the fix they pass.
  • Full Semantics.Test suite on Linux: 1367 passed, 0 failed, 8 skipped (Windows-only path tests). Semantics.sln builds with no errors, so nothing else in the repo relied on V0 negation.

This PR is independent of #342 (#283, which also touches QuantitiesGenerator.cs, in a different region).

🤖 Generated with Claude Code

https://claude.ai/code/session_015i2yeKwKRWtHhdc6NPySjW


Generated by Claude Code

…scalar * and /

The generator already withheld binary '-' from V0 forms, but still emitted
unary negation and unguarded scalar multiplication and division, so
-Temperature.FromKelvin(300) was -300 K and Speed * -3.0 was negative.

V0 forms (bases and overloads) no longer declare unary '-', and their scalar
'*' and '/' run the result through Vector0Guards.EnsureNonNegative, throwing
ArgumentException on a negative scalar. V1 forms are unchanged.

Breaking: code that negated a V0 quantity no longer compiles, and scaling one
by a negative number now throws.

Also corrects complete-library-guide.md, which claimed Speed.Create(-1) throws.

Fixes #285

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015i2yeKwKRWtHhdc6NPySjW
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit c473e84 into main Sep 30, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/vector0-negation-and-scaling branch September 30, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vector0 magnitudes go negative through unary minus and scalar * and /: -Temperature.FromKelvin(300) is −300 K

2 participants