Skip to content

Commit 4015acc

Browse files
authored
Merge pull request #67 from fslaborg/daily-test-improver-matrix-edgecases-20251013-2ca7e096957b431a-d26c74ed55163d81
Daily Test Coverage Improver - Matrix Edge Case Tests
2 parents 45bf8a0 + 651339c commit 4015acc

File tree

2 files changed

+187
-0
lines changed

2 files changed

+187
-0
lines changed

tests/FsMath.Tests/FsMath.Tests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<Compile Include="MatrixFloatTests.fs" />
2828
<Compile Include="MatrixFormattingTests.fs" />
2929
<Compile Include="MatrixAdditionalTests.fs" />
30+
<Compile Include="MatrixEdgeCaseTests.fs" />
3031
<Compile Include="PermutationTests.fs" />
3132
<Compile Include="LinearAlgebraTests.fs" />
3233
<Compile Include="LinearAlgebraCoverageTests.fs" />
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
namespace FsMath.Tests
2+
3+
open Xunit
4+
open FsMath
5+
6+
module MatrixEdgeCaseTests =
7+
8+
// ============================================
9+
// Tests for Matrix indexer setter (line 39)
10+
// ============================================
11+
12+
[<Fact>]
13+
let ``Matrix setter throws on negative row index`` () =
14+
let m = Matrix<float>.zeroCreate 3 3
15+
Assert.Throws<System.ArgumentException>(fun () -> m.[-1, 0] <- 1.0) |> ignore
16+
17+
[<Fact>]
18+
let ``Matrix setter throws on row index too large`` () =
19+
let m = Matrix<float>.zeroCreate 3 3
20+
Assert.Throws<System.ArgumentException>(fun () -> m.[3, 0] <- 1.0) |> ignore
21+
22+
[<Fact>]
23+
let ``Matrix setter throws on negative column index`` () =
24+
let m = Matrix<float>.zeroCreate 3 3
25+
Assert.Throws<System.ArgumentException>(fun () -> m.[0, -1] <- 1.0) |> ignore
26+
27+
[<Fact>]
28+
let ``Matrix setter throws on column index too large`` () =
29+
let m = Matrix<float>.zeroCreate 3 3
30+
Assert.Throws<System.ArgumentException>(fun () -> m.[0, 3] <- 1.0) |> ignore
31+
32+
33+
// ============================================
34+
// Tests for toFormattedString with custom floatFormat (line 272)
35+
// ============================================
36+
37+
[<Fact>]
38+
let ``toFormattedString with custom floatFormat`` () =
39+
let m = Matrix<float>.init 2 2 (fun i j -> float (i + j) + 0.123456)
40+
let formatted = m.toFormattedString(floatFormat = "0.0000")
41+
// Should contain the 4-decimal format
42+
Assert.Contains("0.1235", formatted) // 0.123456 rounded to 4 decimals
43+
44+
[<Fact>]
45+
let ``toFormattedString with custom precision floatFormat`` () =
46+
let m = Matrix<float>.init 2 2 (fun i j -> float (i + j) * 1.5)
47+
let formatted = m.toFormattedString(floatFormat = "0.000")
48+
// Should use the custom format
49+
Assert.Contains("1.500", formatted)
50+
51+
52+
// ============================================
53+
// Tests for toFormattedString truncation message (line 319)
54+
// ============================================
55+
56+
[<Fact>]
57+
let ``toFormattedString shows truncation message for large matrices`` () =
58+
let m = Matrix<float>.init 20 20 (fun i j -> float (i * 10 + j))
59+
let formatted = m.toFormattedString(maxRows = 5, maxCols = 5)
60+
// Should contain truncation message
61+
Assert.Contains("truncated", formatted)
62+
Assert.Contains("(20x20)", formatted)
63+
64+
[<Fact>]
65+
let ``toFormattedString shows truncation for rows exceeding maxRows`` () =
66+
let m = Matrix<int>.init 15 3 (fun i j -> i + j)
67+
let formatted = m.toFormattedString(maxRows = 5)
68+
Assert.Contains("truncated", formatted)
69+
70+
[<Fact>]
71+
let ``toFormattedString shows truncation for cols exceeding maxCols`` () =
72+
let m = Matrix<int>.init 3 15 (fun i j -> i + j)
73+
let formatted = m.toFormattedString(maxCols = 5)
74+
Assert.Contains("truncated", formatted)
75+
76+
77+
// ============================================
78+
// Tests for muliplyVector SIMD path (line 496)
79+
// This tests the accumulation line within the SIMD loop
80+
// ============================================
81+
82+
[<Fact>]
83+
let ``muliplyVector with large vectors exercises SIMD path`` () =
84+
// Create a matrix and vector large enough to use SIMD
85+
let size = 64 // Should be larger than SIMD vector size
86+
let m = Matrix<float>.init size size (fun i j -> if i = j then 1.0 else 0.0) // Identity
87+
let v = Array.init size (fun i -> float (i + 1))
88+
89+
let result = Matrix.muliplyVector m v
90+
91+
// Identity matrix should return the same vector
92+
for i = 0 to size - 1 do
93+
Assert.Equal(float (i + 1), result.[i])
94+
95+
[<Fact>]
96+
let ``muliplyVector with non-trivial matrix exercises SIMD`` () =
97+
let rows = 32
98+
let cols = 32
99+
let m = Matrix<float>.init rows cols (fun i j -> float ((i + 1) * (j + 1)))
100+
let v = Array.init cols (fun i -> 1.0)
101+
102+
let result = Matrix.muliplyVector m v
103+
104+
// Each row sum should be sum of (i+1)*j for j=1 to cols
105+
for i = 0 to rows - 1 do
106+
let expected = float ((i + 1) * cols * (cols + 1) / 2)
107+
Assert.Equal(expected, result.[i])
108+
109+
110+
// ============================================
111+
// Tests for addRowVector SIMD path (line 534)
112+
// ============================================
113+
114+
[<Fact>]
115+
let ``addRowVector with large matrix exercises SIMD path`` () =
116+
let rows = 10
117+
let cols = 64 // Large enough for SIMD
118+
let m = Matrix<float>.zeroCreate rows cols
119+
let v = Array.init cols (fun i -> float i)
120+
121+
let result = Matrix.addRowVector m v
122+
123+
// Every row should be equal to v
124+
for i = 0 to rows - 1 do
125+
for j = 0 to cols - 1 do
126+
Assert.Equal(float j, result.[i, j])
127+
128+
[<Fact>]
129+
let ``addRowVector with varying row data`` () =
130+
let rows = 5
131+
let cols = 48
132+
let m = Matrix<float>.init rows cols (fun i j -> float (i * 10))
133+
let v = Array.init cols (fun i -> float (i + 1))
134+
135+
let result = Matrix.addRowVector m v
136+
137+
// Each row should have base value + v
138+
for i = 0 to rows - 1 do
139+
for j = 0 to cols - 1 do
140+
Assert.Equal(float (i * 10 + j + 1), result.[i, j])
141+
142+
143+
// ============================================
144+
// Tests for addColVector SIMD path (line 572)
145+
// ============================================
146+
147+
[<Fact>]
148+
let ``addColVector with large matrix exercises SIMD path`` () =
149+
let rows = 16
150+
let cols = 64 // Large enough for SIMD
151+
let m = Matrix<float>.zeroCreate rows cols
152+
let v = Array.init rows (fun i -> float i)
153+
154+
let result = Matrix.addColVector m v
155+
156+
// Every element in row i should be equal to v.[i]
157+
for i = 0 to rows - 1 do
158+
for j = 0 to cols - 1 do
159+
Assert.Equal(float i, result.[i, j])
160+
161+
[<Fact>]
162+
let ``addColVector with varying column data`` () =
163+
let rows = 8
164+
let cols = 48
165+
let m = Matrix<float>.init rows cols (fun i j -> float (j * 5))
166+
let v = Array.init rows (fun i -> float (i + 1))
167+
168+
let result = Matrix.addColVector m v
169+
170+
// Each element should have base value + v.[i]
171+
for i = 0 to rows - 1 do
172+
for j = 0 to cols - 1 do
173+
Assert.Equal(float (j * 5 + i + 1), result.[i, j])
174+
175+
[<Fact>]
176+
let ``addColVector with int32 type`` () =
177+
let rows = 6
178+
let cols = 32
179+
let m = Matrix<int>.zeroCreate rows cols
180+
let v = Array.init rows (fun i -> i + 10)
181+
182+
let result = Matrix.addColVector m v
183+
184+
for i = 0 to rows - 1 do
185+
for j = 0 to cols - 1 do
186+
Assert.Equal(i + 10, result.[i, j])

0 commit comments

Comments
 (0)