@@ -265,6 +265,19 @@ public void FixedMatrix4x4_TRS_CreatesCorrectTransformationMatrix()
265265 $ "Expected { rotation } but got { decomposedRotation } ") ;
266266 }
267267
268+ [ Fact ]
269+ public void FixedMatrix4x4_TranslateRotateScale_MatchesExplicitMultiplicationOrder ( )
270+ {
271+ var translation = new Vector3d ( 3 , - 2 , 5 ) ;
272+ var rotation = FixedQuaternion . FromEulerAnglesInDegrees ( ( Fixed64 ) 30 , ( Fixed64 ) 45 , ( Fixed64 ) 60 ) ;
273+ var scale = new Vector3d ( 2 , 3 , 4 ) ;
274+
275+ var expected = Fixed4x4 . CreateTranslation ( translation ) * Fixed4x4 . CreateRotation ( rotation ) * Fixed4x4 . CreateScale ( scale ) ;
276+ var result = Fixed4x4 . TranslateRotateScale ( translation , rotation , scale ) ;
277+
278+ Assert . Equal ( expected , result ) ;
279+ }
280+
268281 [ Fact ]
269282 public void FixedMatrix4x4_Equality_WorksCorrectly ( )
270283 {
@@ -310,6 +323,19 @@ public void FixedMatrix4x4_SetGlobalScale_WorksWithRotation()
310323 Assert . Equal ( globalScale , extractedScale ) ;
311324 }
312325
326+ [ Fact ]
327+ public void FixedMatrix4x4_SetScale_UpdatesDiagonalComponents ( )
328+ {
329+ var matrix = Fixed4x4 . CreateTranslation ( new Vector3d ( 5 , 6 , 7 ) ) ;
330+
331+ var updated = Fixed4x4 . SetScale ( matrix , new Vector3d ( 2 , 3 , 4 ) ) ;
332+
333+ Assert . Equal ( new Fixed64 ( 2 ) , updated . m00 ) ;
334+ Assert . Equal ( new Fixed64 ( 3 ) , updated . m11 ) ;
335+ Assert . Equal ( new Fixed64 ( 4 ) , updated . m22 ) ;
336+ Assert . Equal ( new Vector3d ( 5 , 6 , 7 ) , updated . Translation ) ;
337+ }
338+
313339 [ Fact ]
314340 public void FixedMatrix4x4_SetRotation_PreservesTranslationAndScale ( )
315341 {
@@ -340,6 +366,28 @@ public void FixedMatrix4x4_SetTranslationAndRotationExtensions_UpdateMatrixInPla
340366 Assert . True ( matrix . Rotation . FuzzyEqual ( rotation , new Fixed64 ( 0.0001 ) ) ) ;
341367 }
342368
369+ [ Fact ]
370+ public void FixedMatrix4x4_ExtractRotation_HandlesZeroScaleWithoutThrowing ( )
371+ {
372+ var matrix = Fixed4x4 . CreateScale ( Vector3d . Zero ) ;
373+
374+ var exception = Record . Exception ( ( ) => Fixed4x4 . ExtractRotation ( matrix ) ) ;
375+
376+ Assert . Null ( exception ) ;
377+ }
378+
379+ [ Fact ]
380+ public void FixedMatrix4x4_Decompose_ZeroScaleMatrix_ReplacesZeroScaleToAvoidDivisionByZero ( )
381+ {
382+ var matrix = Fixed4x4 . CreateScale ( Vector3d . Zero ) ;
383+
384+ Assert . True ( Fixed4x4 . Decompose ( matrix , out var scale , out var rotation , out var translation ) ) ;
385+
386+ Assert . Equal ( Vector3d . One , scale ) ;
387+ Assert . Equal ( Vector3d . Zero , translation ) ;
388+ Assert . Equal ( rotation , rotation ) ;
389+ }
390+
343391 [ Fact ]
344392 public void FixedMatrix4x4_NormalizeRotationMatrixExtension_NormalizesAxesInPlace ( )
345393 {
@@ -398,6 +446,15 @@ public void FixedMatrix4x4_Invert_SingularNonAffineMatrix_ReturnsFalse()
398446 Assert . Equal ( Fixed4x4 . Identity , inverted ) ;
399447 }
400448
449+ [ Fact ]
450+ public void FixedMatrix4x4_Invert_SingularAffineMatrix_ReturnsFalse ( )
451+ {
452+ var matrix = Fixed4x4 . CreateScale ( new Vector3d ( 0 , 1 , 1 ) ) ;
453+
454+ Assert . False ( Fixed4x4 . Invert ( matrix , out var inverted ) ) ;
455+ Assert . Equal ( Fixed4x4 . Identity , inverted ) ;
456+ }
457+
401458 [ Fact ]
402459 public void FixedMatrix4x4_TransformPoint_NonAffineMatrix_UsesPerspectiveDivision ( )
403460 {
@@ -540,6 +597,12 @@ public void FixedMatrix4x4_OperatorsAndHashCode_WorkCorrectly()
540597 Assert . NotEqual ( hash , changedM13 . GetHashCode ( ) ) ;
541598 }
542599
600+ [ Fact ]
601+ public void FixedMatrix4x4_EqualsObject_ReturnsFalseForDifferentType ( )
602+ {
603+ Assert . False ( Fixed4x4 . Identity . Equals ( "not-a-matrix" ) ) ;
604+ }
605+
543606 [ Fact ]
544607 public void TransformPoint_WorldToLocal_ReturnsCorrectResult ( )
545608 {
0 commit comments