Commit graph CultLib/packages/cultmath/tests/CultMath.Tests/VectorEqualityTests.cs
Author SHA1 Message Date
Meta Vens
41440cb538 Tie the scalar comparison overloads too, not just vector-vector
The vector-vector self-tie added in the previous commit does not cover
float2/float3/float4's vector-scalar and scalar-vector overloads: their
existing no-tie fixture (a distinct vector against a single scalar) never
had a component equal to that scalar, so their boundary-flip mutants
(< to <=, > to >=) kept surviving. Add a uniform vector (every component
the same value) against a scalar equal to that value, tying every
component of both scalar overloads at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:49:23 +02:00
Meta Vens
eeb67e2a22 Add tied-value comparisons to kill boundary-flip mutants for real
The no-tie fixture in each *ComparisonOperatorsDifferPerComponent test
correctly kills direction mutations (< swapped for >) but leaves every
strict/non-strict boundary swap (< to <=, > to >=) surviving, since with
no equal component the two behave identically. That default is
appropriate for a float-threshold epsilon check, but these are
general-purpose vector comparison operators (CultMath's own
RectIntersectionTreatsTouchingEdgesAsContact test compares literal
endpoints), and for the int types an exact tie is the routine case, not
the rare one. Add a complementary "compared against itself" call per type
(vector-vector for double2/double3/int2/int3/int4, plus vector-scalar and
scalar-vector for float2/float3/float4) so every component ties and the
boundary swaps are actually exercised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:44:58 +02:00
Meta Vens
446859927a Fix degenerate fixtures that let real mutants survive their own tests
Soul-style self-check against the actual mutation report (not just green
tests) found several fixtures whose values coincidentally produced the
same output on the buggy path as on the correct one:

- BatchMath's scalar-tail fixtures put the one remainder particle/step
  either outside the falloff radius or mask-frozen, so the y-axis
  arithmetic a mutation would touch was never reached with an observable
  effect. Pin the remainder particle in range (radial falloff) and dynamic
  (Euler integration) so the scalar tail's own math is exercised, not just
  the vector body's.
- The float2-overload of AddRadialFalloffAcceleration2D had no no-op
  (radius <= 0 / strength == 0) test at all.
- first_order_intercept_time's negative-determinant test used a
  perpendicular relative velocity, making b = 2*dot(vel, pos) exactly
  zero; a mutant that drops the "no solution" branch entirely and falls
  through to the linear fallback coincidentally computes 0 too. Use a
  non-perpendicular fixture so the fallback's nonzero value is
  distinguishable from the correct zero.
- No fixture ever reached the `t1 > 0` branch at all (a > 0, both
  quadratic roots real and positive), so the boundary/negate checks
  guarding it and the `t2 > 0 ? min(t1, t2) : t1` line were never
  covered. Add that case.
- bool2.@false/@true, bool3.@true and bool4.@false have no consumer
  anywhere in the suite (bool3.@false and bool4.@true are read by
  HlslSemanticsTests); pin all six vector constants directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:26:48 +02:00
Meta Vens
ab98462c06 Test vector Equals/GetHashCode/comparison operators per component
Hand-verified that weakening float3.Equals from && to || passes the whole
suite. The same shape recurs with no shared base type across float2/3/4,
double2/3, int2/3/4, bool2/3/4, quaternion, float2x2 and float3x3. Add
data-driven tests, per component position, that a value differing at
exactly one component is unequal under Equals/==/!=, that GetHashCode
stays consistent with Equals, and that </>/<=/>= (including the
vector-scalar and scalar-vector overloads on the float types) each report
a different result per component. float2x2/float3x3 are covered at row
granularity since they have no == operator; quaternion and bool2/3/4 have
no ordering operators and are covered for equality only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:06:41 +02:00