-
Notifications
You must be signed in to change notification settings - Fork 58
Expand file tree
/
Copy pathMatrix.fs
More file actions
1337 lines (1048 loc) · 56.4 KB
/
Matrix.fs
File metadata and controls
1337 lines (1048 loc) · 56.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
module MatrixTests
open Expecto
open FSharp.Stats
open FSharp.Stats.Matrix
let private testRowVecA =
let values = [|1.;4.|]
RowVector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testRowVecB =
let values = [|0.;3.;6.|]
RowVector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testRowVecC =
let values = [|0.;3.;4.|]
RowVector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testRowVecD =
let values = [|0.;0.;0.|]
RowVector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testVectorA =
let values = [|0.;3.;6.|]
Vector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testVectorB =
let values = [|0.;0.;0.|]
Vector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testVector1LowerDiag =
let values = [|0.;5.|]
Vector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testVector1UpperDiag =
let values = [|1.;4.|]
Vector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
let private testDiagonalMatrixA : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
if i = j then
testVectorA.[i]
else 0.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private identity3Int : Matrix<int> =
let values =
Array2D.init
3
3
(fun i j ->
if i = j then 1 else 0
)
Matrix.DenseRepr
(DenseMatrix<int>(Some (Instances.Int32Numerics :> INumeric<int>),values))
let private identityFloat3 =
let values =
Array2D.init
3
3
(fun i j ->
if i = j then 1. else 0.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private testValuesArrRows =
[|
[|0.;1.;2.|]
[|0.;3.;4.|]
[|0.;5.;6.|]
|]
let private testValuesArrCols =
[|
[|0.;0.;0.|]
[|1.;3.;5.|]
[|2.;4.;6.|]
|]
let private testValues2x3 =
[|
[|0.;0.;0.|]
[|1.;3.;5.|]
|]
let private testValues2x3Transposed =
[|
[|0.;1.|]
[|0.;3.|]
[|0.;5.|]
|]
let private testValues3x2 =
[|
[|0.;0.|]
[|1.;3.|]
[|2.;4.|]
|]
let private testSquareMatrixA : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private testSquareMatrixB : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrCols.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private test2x3Matrix : Matrix<float> =
let values =
Array2D.init
2
3
(fun i j ->
testValues2x3.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private test2x3MatrixTransposed : Matrix<float> =
let values =
Array2D.init
3
2
(fun i j ->
testValues2x3Transposed.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private test3x2MatrixB : Matrix<float> =
let values =
Array2D.init
3
2
(fun i j ->
testValues3x2.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private testConstDiagMatrix : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
if i = j then 3. else 0.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private testConstMatrix : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
3.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
let private testScalarMatrix : Matrix<float> =
let values =
Array2D.init
1
1
(fun i j ->
3.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
[<Tests>]
let genericImplementationTests =
testList "Matrix.GenericImplementation" [
//TO-DO: cover generic implementation here, using another numeric then float
testCase "" <| fun () ->
()
]
[<Tests>]
let floatImplementationSparseTests =
testList "Matrix.FloatImplementation.Sparse" [
//TO-DO: adapt all dense tests for sparse matrices
testCase "" <| fun () ->
()
]
[<Tests>]
let floatImplementationDenseTests =
testList "Matrix.FloatImplementation.Dense" [
//Tests for acessing and setting values in the underlying array2D
testList "Acessors" [
testCase "Get value" <| fun () ->
let actual = Matrix.get testSquareMatrixA 0 1
Expect.equal actual 1. "Matrix.get returned wrong value"
testCase "Getting value out of range should fail" <| fun () ->
Expect.throws (fun () -> Matrix.get testSquareMatrixA 0 7 |> ignore) "Getting value out of range should fail"
testCase "Set value" <| fun () ->
let actual =
Matrix.copy testSquareMatrixA
Matrix.set actual 0 0 1337.
let expected =
[
[1337.;1.;2.]
[0.;3.;4.]
[0.;5.;6.]
]
|> matrix
Expect.equal actual expected "Matrix.set mutated the wrong value"
testCase "Setting value out of range should fail" <| fun () ->
Expect.throws (fun () -> Matrix.set (Matrix.copy testSquareMatrixA) 0 7 3. |> ignore) "Getting value out of range should fail"
]
testList "Creation" [
testCase "init" <| fun () ->
let actual =
Matrix.init 3 3 (fun i j -> testValuesArrRows.[i].[j])
Expect.equal actual testSquareMatrixA "Matrix was not initialized correctly using Matrix.init"
testCase "ofRows" <| fun () ->
let actual =
testValues2x3
|> Array.map rowvec
|> Vector.Generic.ofSeq
|> Matrix.ofRows
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofRows"
testCase "ofCols" <| fun () ->
let actual =
testValues2x3Transposed
|> Array.map vector
|> RowVector.Generic.ofSeq
|> Matrix.ofCols
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofCols"
testCase "ofJaggedList" <| fun () ->
let actual =
testValues2x3
|> List.ofArray
|> List.map List.ofArray
|> Matrix.ofJaggedList
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedList"
testCase "ofJaggedColList" <| fun () ->
let actual =
testValues2x3Transposed
|> List.ofArray
|> List.map List.ofArray
|> Matrix.ofJaggedColList
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColList"
testCase "ofJaggedSeq" <| fun () ->
let actual =
testValues2x3
|> Seq.ofArray
|> Seq.map Seq.ofArray
|> Matrix.ofJaggedSeq
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedSeq"
testCase "ofJaggedColSeq" <| fun () ->
let actual =
testValues2x3Transposed
|> Seq.ofArray
|> Seq.map Seq.ofArray
|> Matrix.ofJaggedColSeq
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColSeq"
testCase "ofJaggedArray" <| fun () ->
let actual =
testValues2x3
|> Matrix.ofJaggedArray
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedArray"
testCase "ofJaggedColArray" <| fun () ->
let actual =
testValues2x3Transposed
|> Matrix.ofJaggedColArray
Expect.equal actual test2x3Matrix "Matrix was not initialized correctly using Matrix.ofJaggedColArray"
testCase "diag" <| fun () ->
let actual = Matrix.diag testVectorA
Expect.equal actual testDiagonalMatrixA "Diagonal Matrix was not correctly initialized using Matrix.diag"
testCase "initDiagonal" <| fun () ->
let actual = Matrix.initDiagonal testVectorA
Expect.equal actual testDiagonalMatrixA "Diagonal Matrix was not correctly initialized using Matrix.initDiag"
testCase "constDiag" <| fun () ->
let actual = Matrix.constDiag 3 3.
Expect.equal actual testConstDiagMatrix "Constant diagonal matrix was not correctly initialized using Matrix.constDiag"
testCase "create" <| fun () ->
let actual = Matrix.create 3 3 3.
Expect.equal actual testConstMatrix "Constant matrix was not initialized correctly using Matrix.create"
testCase "ofScalar" <| fun () ->
let actual = Matrix.ofScalar 3.
Expect.equal actual testScalarMatrix "1x1 Matrix was not correctly initialized using Matrix.ofScalar"
testCase "ofArray2D" <| fun () ->
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j]
)
let actual = Matrix.ofArray2D values
Expect.equal actual testSquareMatrixA "Matrix was not initialized correctly using Matrix.ofArray2D"
testCase "toArray2D" <| fun () ->
let expected =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j]
)
let actual = Matrix.toArray2D testSquareMatrixA
Expect.equal actual expected "Matrix.toArray2D did not return the correct Array2D"
testCase "toJaggedArray" <| fun () ->
let actual = Matrix.toJaggedArray testSquareMatrixA
Expect.equal actual testValuesArrRows "Matrix.toJaggedArray did not return the correct JaggedArray"
testCase "toJaggedSeq" <| fun () ->
let actual = Matrix.toJaggedSeq testSquareMatrixA |> JaggedArray.ofJaggedSeq
Expect.equal actual testValuesArrRows "Matrix.toJaggedSeq did not return the correct JaggedSeq"
testCase "toJaggedColArray" <| fun () ->
let actual = Matrix.toJaggedColArray testSquareMatrixA
Expect.equal actual testValuesArrCols "Matrix.toJaggedColArray did not return the correct JaggedArray"
testCase "toJaggedColSeq" <| fun () ->
let actual = Matrix.toJaggedColSeq testSquareMatrixA |> JaggedArray.ofJaggedSeq
Expect.equal actual testValuesArrCols "Matrix.toJaggedColSeq did not return the correct JaggedSeq"
testCase "getDiagN 1 above diagonal" <| fun () ->
let actual = Matrix.getDiagN testSquareMatrixA 1
Expect.equal actual testVector1UpperDiag "Matrix.getDiagN did not return the correct offset +1 diagonal"
testCase "getDiag 1 below diagonal" <| fun () ->
let actual = Matrix.getDiagN testSquareMatrixA -1
Expect.equal actual testVector1LowerDiag "Matrix.getDiagN did not return the correct offset -1 diagonal"
]
testList "Operators" [
testList "add" [
testCase "Addition of 2 Matrices with the same dimensions" <| fun () ->
let actual = Matrix.add testSquareMatrixA testSquareMatrixB
let expected =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] + testValuesArrCols.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Matrix.add did not add the values of two matrices with the same dimensions correctly"
testCase "Addition of matrices with different sizes should fail" <| fun () ->
Expect.throws (fun () -> Matrix.add test2x3Matrix testSquareMatrixA |> ignore) "Addition of Matrices with different dimesnions did not fail although it should"
]
testList "sub" [
testCase "Substraction of 2 Matrices with the same dimensions" <| fun () ->
let actual = Matrix.sub testSquareMatrixA testSquareMatrixB
let expected =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] - testValuesArrCols.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Matrix.add did not add the values of two matrices with the same dimensions correctly"
testCase "Subtraction of matrices with different sizes should fail" <| fun () ->
Expect.throws (fun () -> Matrix.sub test2x3Matrix testSquareMatrixA |> ignore) "Subtraction of Matrices with different dimesnions did not fail although it should"
]
testList "mul" [
testCase "Matrix Multiplication with fitting dimensions" <| fun () ->
let actual = Matrix.mul test2x3Matrix test3x2MatrixB
let expected =
let values =
[
[0.;0.;]
[13.;29.]
]
let valArr =
Array2D.init
2
2
(fun i j ->
values.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),valArr))
Expect.equal actual expected "Matrix multiplication of the 2x3 and 3x2 testmatrices did not return the correct result."
testCase "Matrix Multiplication with non-fitting dimensions should fail" <| fun () ->
Expect.throws (fun () -> Matrix.mul testScalarMatrix testSquareMatrixA |> ignore) "Matrix multiplication with non-fitting dimensions did not fail although it should"
]
testList "mulV" [
testCase "Matrix (m*1)Vector multiplication with correct dimensions" <| fun () ->
let actual = Matrix.mulV testSquareMatrixA testVectorA
let expected =
let values = [|15.;33.;51.|]
Vector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
Expect.equal actual expected "Matrix (m*1)Vector multiplication with correct dimensions did not return the correct result vector"
testCase "Matrix (m*1)Vector multiplication with incorrect dimensions should fail" <| fun () ->
Expect.throws (fun () -> Matrix.mulV testSquareMatrixA testVector1UpperDiag |> ignore) "Matrix (m*1)Vector multiplication with incorrect dimensions should fail although it should"
]
testList "mulRV" [
testCase "Matrix (1*n) RowVector multiplication with correct dimensions" <| fun () ->
let actual = Matrix.mulRV testRowVecB testSquareMatrixA
let expected =
let values = [|0.;39.;48.|]
RowVector<float>(Some (Instances.FloatNumerics :> INumeric<float>),values)
Expect.equal actual expected "Matrix (1*n) RowVector multiplication with correct dimensions did not return the correct result rowVector"
testCase "Matrix (1*n) RowVector multiplication with incorrect dimensions should fail" <| fun () ->
Expect.throws (fun () -> Matrix.mulRV testRowVecA testSquareMatrixA |> ignore) "Matrix (1*n) RowVector multiplication with incorrect dimensions didnt fail although it should"
]
testList "cptMul" [
testCase "Point wise multiplication of two matrices with the same dimensions" <| fun () ->
let actual =
Matrix.cptMul testSquareMatrixA testSquareMatrixB
let expected =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] * testValuesArrCols.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Point wise multiplication of two matrices with the same dimensions did not return the correct result matrix"
testCase "Point wise multiplication of two matrices with different dimensions should fail" <| fun () ->
Expect.throws (fun () -> Matrix.cptMul testSquareMatrixA testScalarMatrix |> ignore) "Point wise multiplication of two matrices with different dimensions did not fail although it should"
]
testList "cptMax" [
testCase "Point wise maximization of two matrices with the same dimensions" <| fun () ->
let actual =
Matrix.cptMax testSquareMatrixA testSquareMatrixB
let expected =
let values =
Array2D.init
3
3
(fun i j ->
max testValuesArrRows.[i].[j] testValuesArrCols.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Point wise maximization of two matrices with the same dimensions did not return the correct result matrix"
testCase "Point wise maximization of two matrices with different dimensions should fail" <| fun () ->
Expect.throws (fun () -> Matrix.cptMax testSquareMatrixA testScalarMatrix |> ignore) "Point wise maximization of two matrices with different dimensions did not fail although it should"
]
testList "cptMin" [
testCase "Point wise minimization of two matrices with the same dimensions" <| fun () ->
let actual =
Matrix.cptMin testSquareMatrixA testSquareMatrixB
let expected =
let values =
Array2D.init
3
3
(fun i j ->
min testValuesArrRows.[i].[j] testValuesArrCols.[i].[j]
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Point wise minimization of two matrices with the same dimensions did not return the correct result matrix"
testCase "Point wise minimization of two matrices with different dimensions should fail" <| fun () ->
Expect.throws (fun () -> Matrix.cptMin testSquareMatrixA testScalarMatrix |> ignore) "Point wise minimization of two matrices with different dimensions did not fail although it should"
]
testList "scale" [
testCase "scale" <| fun () ->
let actual = Matrix.scale 2. testSquareMatrixA
let expected : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] * 2.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Scaling a matrix by a scalar did not return the correctly scaled matrix"
]
testList "neg" [
let actual = Matrix.neg testSquareMatrixA
let expected : Matrix<float> =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] * -1.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Negating a matrix did not return the correctly negated matrix"
]
testList "trace" [
testCase "Trace of a square matrix" <| fun () ->
let actual = Matrix.trace testSquareMatrixA
Expect.equal actual 9. "Trace of a square matrix was not calculated correctly"
testCase "Trace of a non-square matrix should fail" <| fun () ->
Expect.throws (fun () -> Matrix.trace test2x3Matrix |> ignore) "Trace of a non-square matrix did not fail although it should"
]
testList "transpose" [
testCase "transpose of a square matrix" <| fun () ->
let actual = Matrix.transpose testSquareMatrixA
Expect.equal actual testSquareMatrixB "Transposing a test square matrix did not return the correct result"
testCase "transpose of a non-square matrix" <| fun () ->
let actual = Matrix.transpose test2x3Matrix
Expect.equal actual test2x3MatrixTransposed "Transposing a test non-square matrix did not return the correct result"
]
testList "forall" [
testCase "Check if all values in a matrix are >= 0. (expected to be true)" <| fun () ->
Expect.isTrue (Matrix.forall (fun elem -> elem >= 0.) testSquareMatrixA) "test matrix had all values => 0. but the Matrix.forall function failed to recognize"
testCase "Check if all values in a matrix are >= 1. (expected to be false)" <| fun () ->
Expect.isFalse (Matrix.forall (fun elem -> elem >= 1.) testSquareMatrixA) "test matrix did not have all values => 1. but the Matrix.forall function failed to recognize"
]
testList "exists" [
testCase "Check if a testMatrix contains 0. (expected to be true)" <| fun () ->
Expect.isTrue (Matrix.exists (fun elem -> elem = 0.) testSquareMatrixA) "Test matrix was expected to contain a value 0., but Matrix.exists returned false"
testCase "Check if a testMatrix contains 1337. (expected to be false)" <| fun () ->
Expect.isFalse (Matrix.exists (fun elem -> elem = 1337.) testSquareMatrixA) "Test matrix was not expected to contain a value 1337., but Matrix.exists returned true"
]
testList "foralli" [
testCase "Check if all values in a matrix are >= 0. (expected to be true)" <| fun () ->
Expect.isTrue (Matrix.foralli (fun outerI innerI elem -> elem >= 0.) testSquareMatrixA) "test matrix had all values => 0. but the Matrix.forall function failed to recognize"
testCase "Check if all values in a matrix are >= 1. (expected to be false)" <| fun () ->
Expect.isFalse (Matrix.foralli (fun outerI innerI elem -> elem >= 1.) testSquareMatrixA) "test matrix did not have all values => 1. but the Matrix.forall function failed to recognize"
testCase "Check if values on the diagonal in a matrix are >= 0. (expected to be true)" <| fun () ->
Expect.isTrue (Matrix.foralli (fun outerI innerI elem -> if outerI = innerI then elem >= 0. else true) testSquareMatrixA) "test matrix had all diagonal values => 0. but the Matrix.forall function failed to recognize"
testCase "Check if all non-diagonal values in a matrix are >= 1337. (expected to be false)" <| fun () ->
Expect.isFalse (Matrix.foralli (fun outerI innerI elem -> if outerI <> innerI then elem >= 1337. else true) testSquareMatrixA) "test matrix did not have all non-diagonal values => 1337. but the Matrix.foralli function failed to recognize"
]
testList "existsi" [
testCase "Check if a testMatrix contains 0. (expected to be true)" <| fun () ->
Expect.isTrue (Matrix.existsi (fun outerI innerI elem -> elem = 0.) testSquareMatrixA) "Test matrix was expected to contain a value 0., but Matrix.existsi returned false"
testCase "Check if a testMatrix contains 1337. (expected to be false)" <| fun () ->
Expect.isFalse (Matrix.existsi (fun outerI innerI elem -> elem = 1337.) testSquareMatrixA) "Test matrix was not expected to contain a value 1337., but Matrix.existsi returned true"
testCase "Check if a testMatrix contains 0. on the diagonal (expected to be true)" <| fun () ->
Expect.isTrue (Matrix.existsi (fun outerI innerI elem -> if outerI = innerI then elem = 0. else false) testSquareMatrixA) "Test matrix was expected to contain a diagonal value 0., but Matrix.existsi returned false"
testCase "Check if a testMatrix contains a non diagonal value 1337. (expected to be false)" <| fun () ->
Expect.isFalse (Matrix.existsi (fun outerI innerI elem -> if outerI <> innerI then elem = 1337. else false) testSquareMatrixA) "Test matrix was not expected to contain a non-diagonal value 1337., but Matrix.existsi returned true"
]
testList "map" [
testCase "map with (fun elem -> elem * 2)" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.map (fun elem -> elem * 2.)
let expected =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] * 2.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Mapping the values of a test matrix with * 2. did not return the correct result"
testCase "map with multiplication by constant should return the same result as matrix.scale" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.map (fun elem -> elem * 2.)
let expected =
testSquareMatrixA
|> Matrix.scale 2.
Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.scale"
testCase "map with multiplication by constant -1. should return the same result as matrix.neg" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.map (fun elem -> elem * -1.)
let expected =
testSquareMatrixA
|> Matrix.neg
Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.neg"
]
testList "copy" [
testCase "Matrix copy created by Matrix.copy should equal original matrix" <| fun () ->
Expect.equal (Matrix.copy testSquareMatrixA) testSquareMatrixA "Matrix copy created by Matrix.copy was not equal to original matrix"
testCase "Matrix copy created by Matrix.copy should stay the same when original matrix is mutated" <| fun () ->
let testCopyA = Matrix.copy testSquareMatrixA
let testCopyB = Matrix.copy testCopyA
Matrix.set testCopyA 0 0 1337.
Expect.notEqual testCopyA testCopyB "Matrix copy created by Matrix.copy did not stay the same when original matrix is mutated"
]
testList "mapi" [
testCase "mapi with (fun elem -> elem * 2)" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapi (fun i j elem -> elem * 2.)
let expected =
let values =
Array2D.init
3
3
(fun i j ->
testValuesArrRows.[i].[j] * 2.
)
Matrix.DenseRepr
(DenseMatrix<float>(Some (Instances.FloatNumerics :> INumeric<float>),values))
Expect.equal actual expected "Mapping the values of a test matrix with * 2. did not return the correct result"
testCase "map with multiplication by constant should return the same result as matrix.scale" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapi (fun i j elem -> elem * 2.)
let expected =
testSquareMatrixA
|> Matrix.scale 2.
Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.scale"
testCase "map with multiplication by constant -1. should return the same result as matrix.neg" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapi (fun i j elem -> elem * -1.)
let expected =
testSquareMatrixA
|> Matrix.neg
Expect.equal actual expected "map with multiplication by constant did not return the same result as Matrix.neg"
testCase "create identity matrix using mapi" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapi
(fun i j elem ->
if i = j then
1.
else
0.
)
Expect.equal actual identityFloat3 "creating identity matrix using Matrix.mapi failed"
]
testList "mapRows" [
testCase "map with Seq.mean" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapRows Seq.mean
let expected =
Vector.init
3
(fun i -> Seq.mean testValuesArrRows.[i])
Expect.equal actual expected "Mapping the rows of a test matrix with Seq.mean did not return the correct result"
]
testList "mapCols" [
testCase "map with Seq.mean" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapCols Seq.mean
let expected =
RowVector.init 3 (fun i -> Seq.mean testValuesArrCols.[i])
Expect.equal actual expected "Mapping the cols of a test matrix with Seq.mean did not return the correct result"
]
testList "mapiRows" [
testCase "mapi with Seq.mean" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapiRows (fun i x -> float i * Seq.mean x)
let expected =
Vector.init 3 (fun i -> float i * Seq.average testValuesArrRows.[i])
Expect.equal actual expected "Mapping the rows of a test matrix with Seq.mean did not return the correct result"
]
testList "mapiCols" [
testCase "mapi with Seq.mean" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.mapiCols (fun i x -> float i * Seq.mean x)
let expected =
RowVector.init 3 (fun i -> float i * Seq.average testValuesArrCols.[i])
Expect.equal actual expected "Mapping the columns of a test matrix with Seq.mean did not return the correct result"
]
testList "fold" [
testCase "Sum of all matrix entries using Matrix.fold" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.fold (fun acc elem -> acc + elem) 0.
Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.fold"
testCase "count matrix entries using Matrix.fold" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.fold (fun acc _ -> acc + 1) 0
Expect.equal actual 9 "Matrix entries where not correctly counted using Matrix.fold"
]
testList "foldi" [
testCase "Sum of all matrix entries using Matrix.foldi" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.foldi (fun i j acc elem -> acc + elem) 0.
Expect.equal actual 21. "Sum of matrix elements was not correctly computed using Matrix.foldi"
testCase "count matrix entries using Matrix.foldi" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.foldi (fun i j acc _ -> acc + 1) 0
Expect.equal actual 9 "Matrix entries where not correctly counted using Matrix.foldi"
testCase "Calculation of Matrix trace using Matrix.foldi should be equal to the result of the Matrix.trace function" <| fun () ->
let actual =
testSquareMatrixA
|> Matrix.foldi
(fun i j acc elem ->
if i = j then
acc + elem
else
acc
)
0.
Expect.equal actual (Matrix.trace testSquareMatrixA) "Results of Matrix.trace and calculating matrix trace with Matrix.foldi where not equal"
]
testList "filterRows" [
testCase "simple filter by sum" <| fun () ->
let expected =
matrix [
[1.;2.]
[2.;1.]
]
let actual =
matrix [
[5.;5.]
[1.;2.]
[5.;5.]
[2.;1.]
[5.;5.]
[5.;5.]
]
|> Matrix.filterRows (fun r -> r |> Seq.sum = 3.)
Expect.equal actual expected "Matrix.filterRows did not return correct result"
testCase "simple filter by contains" <| fun () ->
let expected =
matrix [
[1.;100.]
[2.;100.]
]
let actual =
matrix [
[5.;5.]
[1.;2.]
[5.;5.]
[1.;100.]
[2.;100.]
[2.;1.]
[5.;5.]
[5.;5.]
]
|> Matrix.filterRows (fun r -> r |> Seq.contains 100.)
Expect.equal actual expected "Matrix.filterRows did not return correct result"
]
testList "filterCols" [
testCase "simple filter by sum" <| fun () ->
let expected =
matrix [
[1.;2.]
[2.;1.]
]
let actual =
matrix [
[5.;1.;6.;2.;0.]
[5.;2.;6.;1.;0.]
]
|> Matrix.filterCols (fun c -> c |> Seq.sum = 3.)
Expect.equal actual expected "Matrix.filterCols did not return correct result"
testCase "simple filter by contains" <| fun () ->
let expected =
matrix [
[100.;2.]
[2.;100.]
]
let actual =
matrix [
[5.;100.;6.;2.;0.]
[5.;2.;6.;100.;0.]
]
|> Matrix.filterCols (fun c -> c |> Seq.contains 100.)
Expect.equal actual expected "Matrix.filterCols did not return correct result"
]
testList "filterCols" [
]
testList "toDense" [
testCase "toDense" <| fun () ->
()
]
testList "initDense" [
testCase "initDense" <| fun () ->
()
]
testList "initSparse" [
testCase "initSparse" <| fun () ->
()
]
testList "nonzero_entries" [
testCase "nonzero_entries" <| fun () ->
let actual =
Matrix.nonzero_entries testSquareMatrixA
|> Array.ofSeq
let expected =
testValuesArrRows
|> Array.mapi
(fun outerI row ->
row
|> Array.mapi