diff --git a/FsharpSln.sln b/FsharpSln.sln
index a9c1631..f244678 100644
--- a/FsharpSln.sln
+++ b/FsharpSln.sln
@@ -9,6 +9,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LibHw2", "src\LibHw2\LibHw2
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Test", "Test\Test.fsproj", "{363D4F3B-6E01-4E01-9616-7C95DFB0F5B6}"
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LibHw7", "src\LibHw7\LibHw7.fsproj", "{50335321-2C50-43C0-8F8F-436AAEDF2D43}"
+EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ImageProcessing", "src\ImageProcessing\ImageProcessing.fsproj", "{3C564DE7-3B68-4DAE-AD09-F1987066BA36}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LibHw3", "src\LibHw3\LibHw3.fsproj", "{E63C1F63-167B-47D5-A94C-6C00CDAC9104}"
@@ -32,13 +34,13 @@ Global
{363D4F3B-6E01-4E01-9616-7C95DFB0F5B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{363D4F3B-6E01-4E01-9616-7C95DFB0F5B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{363D4F3B-6E01-4E01-9616-7C95DFB0F5B6}.Release|Any CPU.Build.0 = Release|Any CPU
- {3C564DE7-3B68-4DAE-AD09-F1987066BA36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3C564DE7-3B68-4DAE-AD09-F1987066BA36}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3C564DE7-3B68-4DAE-AD09-F1987066BA36}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3C564DE7-3B68-4DAE-AD09-F1987066BA36}.Release|Any CPU.Build.0 = Release|Any CPU
+ {50335321-2C50-43C0-8F8F-436AAEDF2D43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {50335321-2C50-43C0-8F8F-436AAEDF2D43}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {50335321-2C50-43C0-8F8F-436AAEDF2D43}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50335321-2C50-43C0-8F8F-436AAEDF2D43}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{07D1365E-068B-4B9D-999D-4F9C3B544697} = {C3F2792A-709B-4169-ADE4-3D55DC717452}
{EEDB2603-0992-464E-B575-A9A5E31DFA3B} = {C3F2792A-709B-4169-ADE4-3D55DC717452}
EndGlobalSection
-EndGlobal
+EndGlobal
\ No newline at end of file
diff --git a/Test/Test.fsproj b/Test/Test.fsproj
index efc6067..33326eb 100644
--- a/Test/Test.fsproj
+++ b/Test/Test.fsproj
@@ -9,9 +9,7 @@
-
-
-
+
@@ -31,10 +29,7 @@
-
-
-
-
+
diff --git a/Test/TestsHw7.fs b/Test/TestsHw7.fs
new file mode 100644
index 0000000..bc3018a
--- /dev/null
+++ b/Test/TestsHw7.fs
@@ -0,0 +1,164 @@
+namespace tests
+
+open System
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+open QuattroMatrix
+open QuattroMatrix.Matrix
+
+module PropertyQtreeTest =
+
+ let toArray (mat: 'T array2d) : 'T array =
+ let height = Array2D.length1 mat
+ let width = Array2D.length2 mat
+ Array.init (height * width) (fun i ->
+ let row = i / width
+ let col = i % width
+ mat.[row, col]
+ )
+
+ let multMatr mulFunc addFunc mat1 mat2 =
+ if Array2D.length1 mat1 <> Array2D.length2 mat2
+ then failwith "Matrices have different sizes"
+ else
+ let multedMat = Array2D.zeroCreate (Array2D.length1 mat1) (Array2D.length2 mat2)
+ for i in 0 .. Array2D.length1 mat1 - 1 do
+ for j in 0 .. Array2D.length2 mat1 - 1 do
+ for k in 0 .. Array2D.length2 mat2 - 1 do
+ multedMat[i,j] <- addFunc multedMat[i,j] (mulFunc mat1[i,k] mat2[k,j])
+ multedMat
+
+ let createMaped2Matr func matr1 matr2 =
+ let rmatr1 = toArray matr1
+ let rmatr2 = toArray matr2
+ let resMatr = Array.map2 func rmatr1 rmatr2
+ resMatr
+
+ let createQtree matr =
+ let sqmatr = createSquareMatrix matr
+ let qmatr = createQuadMatrix sqmatr 0 0 (Array2D.length1 sqmatr)
+ qmatr, Array2D.length1 sqmatr
+
+ let createFinalMatrix (qtree: QuadMatrix<'T>) qsize heigth wide =
+ let qmatr2d = toArray2d qtree qsize
+ let actmatr = Array2D.create heigth wide Unchecked.defaultof<'T>
+ for i in 0 .. heigth - 1 do
+ for j in 0 .. wide - 1 do
+ actmatr[i, j] <- qmatr2d[i, j]
+ actmatr
+
+ let matrixGenerator rows cols (elementGen: Gen<'T>) : Gen<'T[,]> =
+ let genMatrix =
+ gen {
+ let! elements = Gen.array2DOfDim (rows, cols) elementGen
+ return elements
+ }
+ genMatrix
+
+ let testMap matr size func =
+ let heigth = Array2D.length1 matr
+ let wide = Array2D.length2 matr
+ let expmatr = Array2D.map func matr
+ let qmatr, qsize = createQtree matr
+ let mapedMatr = map func qmatr
+ let actmatr = createFinalMatrix mapedMatr qsize heigth wide
+ expmatr, actmatr
+
+ let testMap2 matr1 matr2 size func =
+ let expmatr = createMaped2Matr func matr1 matr2
+ let qmatr1, qsize1 = createQtree matr1
+ let qmatr2, qsize2 = createQtree matr2
+ let actqmatr = map2 func qmatr1 qmatr2
+ let actmatr2d = createFinalMatrix actqmatr qsize1 size size
+ let actmatr = toArray actmatr2d
+ let fequal = Array.forall2 (=) actmatr expmatr
+ fequal
+
+ let testMult matr1 matr2 size mulFunc addFunc =
+ let expmatr= multMatr mulFunc addFunc matr1 matr2
+ let qmatr1, qsize1 = createQtree matr1
+ let qmatr2, qsize2 = createQtree matr2
+ let actqmatr = multiplyMatrix mulFunc addFunc qmatr1 qsize1 qmatr2 qsize2
+ let actmatr = createFinalMatrix actqmatr qsize1 size size
+ expmatr, actmatr
+
+ []
+ type idTests() =
+
+ []
+ member _.intTest (matr: int array2d) =
+ let qmatr, qsize = PropertyQtreeTest.createQtree matr
+ let mapedMatr = map id qmatr
+ Assert.Equal(qmatr, mapedMatr)
+
+ []
+ member _.floatTest (matr: float32 array2d) =
+ let qmatr, qsize = PropertyQtreeTest.createQtree matr
+ let mapedMatr = map id qmatr
+ Assert.Equal(qmatr, mapedMatr)
+
+ []
+ member _.charTest (matr: char array2d) =
+ let qmatr, qsize = PropertyQtreeTest.createQtree matr
+ let mapedMatr = map id qmatr
+ Assert.Equal(qmatr, mapedMatr)
+
+ type mapTest() =
+
+ []
+ member _.intTest (size: uint) =
+ let matr = Gen.sample (int size) 1 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {-100000..100000}))
+ let expmatr, actmatr = PropertyQtreeTest.testMap matr.[0] (int size) ((+) 1)
+ Assert.Equal(expmatr, actmatr)
+
+ []
+ member _.charTest (size: uint) =
+ let matr = Gen.sample (int size) 1 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {' '..'~'}))
+ let expmatr, actmatr = PropertyQtreeTest.testMap matr.[0] (int size) ((+) '1')
+ Assert.Equal(expmatr, actmatr)
+
+ []
+ member _.floatTest (size: uint) =
+ let matr = Gen.sample (int size) 1 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {-infinityf..infinityf}))
+ let expmatr, actmatr = PropertyQtreeTest.testMap matr.[0] (int size) ((+) 1f)
+ Assert.Equal(expmatr, actmatr)
+
+ type map2Test()=
+
+ []
+ member _.intTest (size: uint) =
+ let matr = Gen.sample (int size) 2 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {-100000..100000}))
+ let fequal = PropertyQtreeTest.testMap2 matr.[0] matr.[1] (int (int size))(+)
+ Assert.True(fequal)
+
+ []
+ member _.charTest (size: uint) =
+ let matr = Gen.sample (int size) 2 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {' '..'~'}))
+ let fequal = PropertyQtreeTest.testMap2 matr.[0] matr.[1] (int (int size))(+)
+ Assert.True(fequal)
+
+ []
+ member _.floatTest (size: uint) =
+ let matr = Gen.sample (int size) 2 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements{-infinityf..infinityf}))
+ let fequal = PropertyQtreeTest.testMap2 matr.[0] matr.[1] (int (int size))(+)
+ Assert.True(fequal)
+
+ type multTest() =
+
+ []
+ member _.intTest (size: uint) =
+ let matr = Gen.sample (int size) 2 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {-100000..100000}))
+ let expmatr, actmatr = PropertyQtreeTest.testMult matr.[0] matr.[1] (int (int size)) ( * ) (+)
+ Assert.Equal(expmatr, actmatr)
+
+ []
+ member _.charTest (size: uint) =
+ let matr = Gen.sample (int size) 2 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {' ' .. '~'}))
+ let expmatr, actmatr = PropertyQtreeTest.testMult matr.[0] matr.[1] (int (int size)) (fun x y -> char (int x * int y)) (+)
+ Assert.Equal(expmatr, actmatr)
+ []
+ member _.floatTest (size: uint) =
+ let matr = Gen.sample (int size) 2 (PropertyQtreeTest.matrixGenerator (int size) (int size) (Gen.elements {-infinityf .. infinityf}))
+ let expmatr, actmatr = PropertyQtreeTest.testMult matr.[0] matr.[1] (int (int size)) ( * ) (+)
+ Assert.Equal(expmatr, actmatr)
\ No newline at end of file
diff --git a/src/LibHw7/LibHw7.fsproj b/src/LibHw7/LibHw7.fsproj
new file mode 100644
index 0000000..f81f7f5
--- /dev/null
+++ b/src/LibHw7/LibHw7.fsproj
@@ -0,0 +1,12 @@
+
+
+
+ net8.0
+ true
+
+
+
+
+
+
+
diff --git a/src/LibHw7/Library.fs b/src/LibHw7/Library.fs
new file mode 100644
index 0000000..f3ec6e9
--- /dev/null
+++ b/src/LibHw7/Library.fs
@@ -0,0 +1,179 @@
+namespace QuattroMatrix
+
+open System
+
+module Matrix =
+ type QuadMatrix<'T> =
+ | Leaf of 'T
+ | Node of QuadMatrix<'T> * QuadMatrix<'T> * QuadMatrix<'T> * QuadMatrix<'T>
+
+ let createSquareMatrix (inmatr: 'T array2d) =
+ let logSize =
+ if Array2D.length2 inmatr = 0 then
+ 0.0
+ else
+ max (Math.Log2(Array2D.length1 inmatr)) (Math.Log2(Array2D.length2 inmatr))
+
+ let isSizeCorrect = logSize = float (int logSize)
+
+ if
+ not isSizeCorrect
+ || Array2D.length1 inmatr <> Array2D.length2 inmatr
+ || Array2D.length1 inmatr = 0
+ then
+ let normalSize = pown 2 (int logSize + 1)
+
+ let resMatr: 'T array2d =
+ Array2D.create normalSize normalSize Unchecked.defaultof<'T>
+
+ for i in 0 .. Array2D.length1 inmatr - 1 do
+ for j in 0 .. Array2D.length2 inmatr - 1 do
+ resMatr[i, j] <- inmatr[i, j]
+
+ resMatr
+ else
+ let resMatr = inmatr
+ resMatr
+
+ let rec createQuadMatrix (sqmatr: 'T array2d) icorner jcorner size =
+ let mutable isEqualMatr = true
+ let value = sqmatr[icorner, jcorner]
+ let mutable i = icorner
+ let mutable j = jcorner
+
+ while i < icorner + size && isEqualMatr do
+ while j < jcorner + size && isEqualMatr do
+ if value <> sqmatr[i, j] then
+ isEqualMatr <- false
+
+ j <- j + 1
+
+ i <- i + 1
+ j <- jcorner
+
+ if isEqualMatr then
+ Leaf(value)
+ else
+ let halfsize = size / 2
+
+ Node(
+ createQuadMatrix sqmatr icorner jcorner halfsize,
+ createQuadMatrix sqmatr icorner (jcorner + halfsize) halfsize,
+ createQuadMatrix sqmatr (icorner + halfsize) jcorner halfsize,
+ createQuadMatrix sqmatr (icorner + halfsize) (jcorner + halfsize) halfsize
+ )
+
+ let rec map func qtree =
+ match qtree with
+ | Leaf(value) -> Leaf(func value)
+ | Node(t1, t2, t3, t4) -> Node(map func t1, map func t2, map func t3, map func t4)
+
+ let rec map2 func qtree1 qtree2 =
+ match qtree1, qtree2 with
+ | Leaf(value1), Leaf(value2) -> Leaf(func value1 value2)
+ | Leaf(value1), Node(t2_1, t2_2, t2_3, t2_4) ->
+ Node(map2 func qtree1 t2_1, map2 func qtree1 t2_2, map2 func qtree1 t2_3, map2 func qtree1 t2_4)
+ | Node(t1_1, t1_2, t1_3, t1_4), Leaf(value2) ->
+ Node(map2 func t1_1 qtree2, map2 func t1_2 qtree2, map2 func t1_3 qtree2, map2 func t1_4 qtree2)
+ | Node(t1_1, t1_2, t1_3, t1_4), Node(t2_1, t2_2, t2_3, t2_4) ->
+ Node(map2 func t1_1 t2_1, map2 func t1_2 t2_2, map2 func t1_3 t2_3, map2 func t1_4 t2_4)
+
+ let rec add addFunc qtree1 size1 qtree2 size2 =
+ match qtree1, qtree2 with
+ | Leaf(value1), Leaf(value2) -> Leaf(addFunc value1 value2)
+ | Leaf(value1), Node(t2_1, t2_2, t2_3, t2_4) ->
+ Node(
+ add addFunc qtree1 (size1 / 2) t2_1 (size2 / 2),
+ add addFunc qtree1 (size1 / 2) t2_2 (size2 / 2),
+ add addFunc qtree1 (size1 / 2) t2_3 (size2 / 2),
+ add addFunc qtree1 (size1 / 2) t2_4 (size2 / 2)
+ )
+ | Node(t1_1, t1_2, t1_3, t1_4), Leaf(value2) ->
+ Node(
+ add addFunc t1_1 (size1 / 2) qtree2 (size2 / 2),
+ add addFunc t1_2 (size1 / 2) qtree2 (size2 / 2),
+ add addFunc t1_3 (size1 / 2) qtree2 (size2 / 2),
+ add addFunc t1_4 (size1 / 2) qtree2 (size2 / 2)
+ )
+ | Node(t1_1, t1_2, t1_3, t1_4), Node(t2_1, t2_2, t2_3, t2_4) ->
+ Node(
+ add addFunc t1_1 (size1 / 2) t2_1 (size2 / 2),
+ add addFunc t1_2 (size1 / 2) t2_2 (size2 / 2),
+ add addFunc t1_3 (size1 / 2) t2_3 (size2 / 2),
+ add addFunc t1_4 (size1 / 2) t2_4 (size2 / 2)
+ )
+
+ let rec multiplyMatrix mulFunc addFunc qtree1 size1 qtree2 size2 =
+ match qtree1, qtree2 with
+ | Leaf(value1), Leaf(value2) -> Leaf(mulFunc value1 value2)
+ | Leaf(value1), Node(t2_1, t2_2, t2_3, t2_4) ->
+ let a = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_1 (size2 / 2)
+ let b = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_3 (size2 / 2)
+ let c = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_2 (size2 / 2)
+ let d = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_4 (size2 / 2)
+ let e = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_1 (size2 / 2)
+ let f = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_3 (size2 / 2)
+ let g = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_2 (size2 / 2)
+ let h = multiplyMatrix mulFunc addFunc qtree1 (size1 / 2) t2_4 (size2 / 2)
+
+ Node(
+ add addFunc a (size1 / 2) b (size2 / 2),
+ add addFunc c (size1 / 2) d (size2 / 2),
+ add addFunc e (size1 / 2) f (size2 / 2),
+ add addFunc g (size1 / 2) h (size2 / 2)
+ )
+ | Node(t1_1, t1_2, t1_3, t1_4), Leaf(value2) ->
+ let a = multiplyMatrix mulFunc addFunc t1_1 (size1 / 2) qtree2 (size2 / 2)
+ let b = multiplyMatrix mulFunc addFunc t1_2 (size1 / 2) qtree2 (size2 / 2)
+ let c = multiplyMatrix mulFunc addFunc t1_1 (size1 / 2) qtree2 (size2 / 2)
+ let d = multiplyMatrix mulFunc addFunc t1_2 (size1 / 2) qtree2 (size2 / 2)
+ let e = multiplyMatrix mulFunc addFunc t1_3 (size1 / 2) qtree2 (size2 / 2)
+ let f = multiplyMatrix mulFunc addFunc t1_4 (size1 / 2) qtree2 (size2 / 2)
+ let g = multiplyMatrix mulFunc addFunc t1_3 (size1 / 2) qtree2 (size2 / 2)
+ let h = multiplyMatrix mulFunc addFunc t1_4 (size1 / 2) qtree2 (size2 / 2)
+
+ Node(
+ add addFunc a (size1 / 2) b (size2 / 2),
+ add addFunc c (size1 / 2) d (size2 / 2),
+ add addFunc e (size1 / 2) f (size2 / 2),
+ add addFunc g (size1 / 2) h (size2 / 2)
+ )
+ | Node(t1_1, t1_2, t1_3, t1_4), Node(t2_1, t2_2, t2_3, t2_4) ->
+ let a = multiplyMatrix mulFunc addFunc t1_1 (size1 / 2) t2_1 (size2 / 2)
+ let b = multiplyMatrix mulFunc addFunc t1_2 (size1 / 2) t2_3 (size2 / 2)
+ let c = multiplyMatrix mulFunc addFunc t1_1 (size1 / 2) t2_2 (size2 / 2)
+ let d = multiplyMatrix mulFunc addFunc t1_2 (size1 / 2) t2_4 (size2 / 2)
+ let e = multiplyMatrix mulFunc addFunc t1_3 (size1 / 2) t2_1 (size2 / 2)
+ let f = multiplyMatrix mulFunc addFunc t1_4 (size1 / 2) t2_3 (size2 / 2)
+ let g = multiplyMatrix mulFunc addFunc t1_3 (size1 / 2) t2_2 (size2 / 2)
+ let h = multiplyMatrix mulFunc addFunc t1_4 (size1 / 2) t2_4 (size2 / 2)
+
+ Node(
+ add addFunc a (size1 / 2) b (size2 / 2),
+ add addFunc c (size1 / 2) d (size2 / 2),
+ add addFunc e (size1 / 2) f (size2 / 2),
+ add addFunc g (size1 / 2) h (size2 / 2)
+ )
+
+ let rec toArray2d (qtree: QuadMatrix<'T>) sizem =
+ match qtree with
+ | Leaf(value) ->
+ let matr = Array2D.create sizem sizem value
+ matr
+ | Node(t1, t2, t3, t4) ->
+ let topleft = toArray2d t1 (sizem / 2)
+ let topright = toArray2d t2 (sizem / 2)
+ let botleft = toArray2d t3 (sizem / 2)
+ let botright = toArray2d t4 (sizem / 2)
+ let size = Array2D.length1 topleft
+
+ let resmatr = Array2D.create sizem sizem Unchecked.defaultof<'T>
+
+ for i in 0 .. size - 1 do
+ for j in 0 .. size - 1 do
+ resmatr[i, j] <- topleft[i, j]
+ resmatr[i, j + size] <- topright[i, j]
+ resmatr[i + size, j] <- botleft[i, j]
+ resmatr[i + size, j + size] <- botright[i, j]
+
+ resmatr
\ No newline at end of file