diff --git a/.gitignore b/.gitignore
index 15a14fd0..60b2ea06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,400 @@
-src/Library/bin/
-src/Library/obj/
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
-Tests/bin/
-Tests/obj/
-Tests/TestResults/
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
-Benchmarks/bin/
-Benchmarks/obj/
-Benchmarks/BenchmarkDotNet.Artifacts/
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
-GraphsAndStatistics/venv/
\ No newline at end of file
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+# but not Directory.Build.rsp, as it configures directory-level build defaults
+!Directory.Build.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
\ No newline at end of file
diff --git a/Benchmarks/Benchmarks.fsproj b/Benchmarks/Benchmarks.fsproj
index f08f2399..5d5d8caf 100644
--- a/Benchmarks/Benchmarks.fsproj
+++ b/Benchmarks/Benchmarks.fsproj
@@ -9,12 +9,12 @@
-
-
+
+
-
-
+
+
diff --git a/GraphsAndStatistics/Array Performance.png b/GraphicsAndStatistics/Array Performance.png
similarity index 100%
rename from GraphsAndStatistics/Array Performance.png
rename to GraphicsAndStatistics/Array Performance.png
diff --git a/GraphsAndStatistics/BubbleCompare.png b/GraphicsAndStatistics/BubbleCompare.png
similarity index 100%
rename from GraphsAndStatistics/BubbleCompare.png
rename to GraphicsAndStatistics/BubbleCompare.png
diff --git a/GraphsAndStatistics/MergeCompare.png b/GraphicsAndStatistics/MergeCompare.png
similarity index 100%
rename from GraphsAndStatistics/MergeCompare.png
rename to GraphicsAndStatistics/MergeCompare.png
diff --git a/GraphsAndStatistics/MyList Performance.png b/GraphicsAndStatistics/MyList Performance.png
similarity index 100%
rename from GraphsAndStatistics/MyList Performance.png
rename to GraphicsAndStatistics/MyList Performance.png
diff --git a/GraphsAndStatistics/QuickCompare.png b/GraphicsAndStatistics/QuickCompare.png
similarity index 100%
rename from GraphsAndStatistics/QuickCompare.png
rename to GraphicsAndStatistics/QuickCompare.png
diff --git a/GraphsAndStatistics/main.py b/GraphicsAndStatistics/main.py
similarity index 100%
rename from GraphsAndStatistics/main.py
rename to GraphicsAndStatistics/main.py
diff --git a/GraphicsAndStatistics/presentation.pdf b/GraphicsAndStatistics/presentation.pdf
new file mode 100644
index 00000000..58d7034d
Binary files /dev/null and b/GraphicsAndStatistics/presentation.pdf differ
diff --git a/HomeWork.sln b/HomeWork.sln
index 36ce6c22..47714e54 100644
--- a/HomeWork.sln
+++ b/HomeWork.sln
@@ -5,12 +5,34 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{00DFC406-0A95-4C11-8BF2-4FD28C28061D}"
EndProject
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Library", "src\Library\Library.fsproj", "{B853FD9B-45DA-4524-8E5D-9BDC24C29F63}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}"
EndProject
-Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Tests", "Tests\Tests.fsproj", "{8FFAF33E-03C8-4A55-84E1-C42E0C602625}"
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Functions", "src\Functions\Functions.fsproj", "{F793D6BB-E68A-473E-B11F-1D7888DF4D4A}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FunctionsT", "Tests\FunctionsT\FunctionsT.fsproj", "{66214A3F-2D3A-4A98-8A9E-25412278BABD}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Sortings", "src\Sortings\Sortings.fsproj", "{55D388AF-E9D9-4EC0-923A-0735BFD93CB8}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "SortingsT", "Tests\SortingsT\SortingsT.fsproj", "{1D6CFA13-FD9D-4586-A463-1C023123E2CA}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Benchmarks", "Benchmarks\Benchmarks.fsproj", "{66023F5A-8456-4F66-9318-A0BFB68ED14A}"
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ImageProcessing", "src\ImageProcessing\ImageProcessing.fsproj", "{7B9D1692-F56C-43C7-92BA-2CDDE21A7D57}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ImageProcessingT", "Tests\ImageProcessingT\ImageProcessingT.fsproj", "{EB2F699B-DE06-42EC-974A-A2C39E5C8D2A}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Trees", "src\Trees\Trees.fsproj", "{CAC5303C-D4CF-493E-94B4-4409BE7F2865}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TreesT", "Tests\TreesT\TreesT.fsproj", "{7E4032B2-27F7-4691-8474-5C57A97F5721}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LineralAlgebra", "src\LineralAlgebra\LineralAlgebra.fsproj", "{C05FDC93-8EE3-442C-868A-031CE2A5F4E4}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LineralAlgebraT", "Tests\LineralAlgebraT\LineralAlgebraT.fsproj", "{C42A6017-8A61-4469-8FCD-EEBF49198D80}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Graphs", "src\Graphs\Graphs.fsproj", "{CF32EADA-1A26-456B-AA5D-075444540057}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "GraphsT", "Tests\GraphsT\GraphsT.fsproj", "{E39D15F4-AE96-42ED-957D-D335208D8BF9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -20,20 +42,71 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B853FD9B-45DA-4524-8E5D-9BDC24C29F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B853FD9B-45DA-4524-8E5D-9BDC24C29F63}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B853FD9B-45DA-4524-8E5D-9BDC24C29F63}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B853FD9B-45DA-4524-8E5D-9BDC24C29F63}.Release|Any CPU.Build.0 = Release|Any CPU
- {8FFAF33E-03C8-4A55-84E1-C42E0C602625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8FFAF33E-03C8-4A55-84E1-C42E0C602625}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8FFAF33E-03C8-4A55-84E1-C42E0C602625}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8FFAF33E-03C8-4A55-84E1-C42E0C602625}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F793D6BB-E68A-473E-B11F-1D7888DF4D4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F793D6BB-E68A-473E-B11F-1D7888DF4D4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F793D6BB-E68A-473E-B11F-1D7888DF4D4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F793D6BB-E68A-473E-B11F-1D7888DF4D4A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {66214A3F-2D3A-4A98-8A9E-25412278BABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66214A3F-2D3A-4A98-8A9E-25412278BABD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66214A3F-2D3A-4A98-8A9E-25412278BABD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66214A3F-2D3A-4A98-8A9E-25412278BABD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {55D388AF-E9D9-4EC0-923A-0735BFD93CB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {55D388AF-E9D9-4EC0-923A-0735BFD93CB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {55D388AF-E9D9-4EC0-923A-0735BFD93CB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {55D388AF-E9D9-4EC0-923A-0735BFD93CB8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1D6CFA13-FD9D-4586-A463-1C023123E2CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1D6CFA13-FD9D-4586-A463-1C023123E2CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1D6CFA13-FD9D-4586-A463-1C023123E2CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1D6CFA13-FD9D-4586-A463-1C023123E2CA}.Release|Any CPU.Build.0 = Release|Any CPU
{66023F5A-8456-4F66-9318-A0BFB68ED14A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66023F5A-8456-4F66-9318-A0BFB68ED14A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66023F5A-8456-4F66-9318-A0BFB68ED14A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66023F5A-8456-4F66-9318-A0BFB68ED14A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7B9D1692-F56C-43C7-92BA-2CDDE21A7D57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7B9D1692-F56C-43C7-92BA-2CDDE21A7D57}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7B9D1692-F56C-43C7-92BA-2CDDE21A7D57}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7B9D1692-F56C-43C7-92BA-2CDDE21A7D57}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EB2F699B-DE06-42EC-974A-A2C39E5C8D2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EB2F699B-DE06-42EC-974A-A2C39E5C8D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EB2F699B-DE06-42EC-974A-A2C39E5C8D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EB2F699B-DE06-42EC-974A-A2C39E5C8D2A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CAC5303C-D4CF-493E-94B4-4409BE7F2865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CAC5303C-D4CF-493E-94B4-4409BE7F2865}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CAC5303C-D4CF-493E-94B4-4409BE7F2865}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CAC5303C-D4CF-493E-94B4-4409BE7F2865}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7E4032B2-27F7-4691-8474-5C57A97F5721}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7E4032B2-27F7-4691-8474-5C57A97F5721}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7E4032B2-27F7-4691-8474-5C57A97F5721}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7E4032B2-27F7-4691-8474-5C57A97F5721}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C05FDC93-8EE3-442C-868A-031CE2A5F4E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C05FDC93-8EE3-442C-868A-031CE2A5F4E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C05FDC93-8EE3-442C-868A-031CE2A5F4E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C05FDC93-8EE3-442C-868A-031CE2A5F4E4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C42A6017-8A61-4469-8FCD-EEBF49198D80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42A6017-8A61-4469-8FCD-EEBF49198D80}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C42A6017-8A61-4469-8FCD-EEBF49198D80}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C42A6017-8A61-4469-8FCD-EEBF49198D80}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CF32EADA-1A26-456B-AA5D-075444540057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CF32EADA-1A26-456B-AA5D-075444540057}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CF32EADA-1A26-456B-AA5D-075444540057}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CF32EADA-1A26-456B-AA5D-075444540057}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E39D15F4-AE96-42ED-957D-D335208D8BF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E39D15F4-AE96-42ED-957D-D335208D8BF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E39D15F4-AE96-42ED-957D-D335208D8BF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E39D15F4-AE96-42ED-957D-D335208D8BF9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {B853FD9B-45DA-4524-8E5D-9BDC24C29F63} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {F793D6BB-E68A-473E-B11F-1D7888DF4D4A} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {66214A3F-2D3A-4A98-8A9E-25412278BABD} = {B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}
+ {55D388AF-E9D9-4EC0-923A-0735BFD93CB8} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {1D6CFA13-FD9D-4586-A463-1C023123E2CA} = {B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}
+ {7B9D1692-F56C-43C7-92BA-2CDDE21A7D57} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {EB2F699B-DE06-42EC-974A-A2C39E5C8D2A} = {B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}
+ {CAC5303C-D4CF-493E-94B4-4409BE7F2865} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {7E4032B2-27F7-4691-8474-5C57A97F5721} = {B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}
+ {C05FDC93-8EE3-442C-868A-031CE2A5F4E4} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {C42A6017-8A61-4469-8FCD-EEBF49198D80} = {B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}
+ {CF32EADA-1A26-456B-AA5D-075444540057} = {00DFC406-0A95-4C11-8BF2-4FD28C28061D}
+ {E39D15F4-AE96-42ED-957D-D335208D8BF9} = {B4AC50D2-34AD-46DF-B39E-FBCC5D0653C6}
EndGlobalSection
EndGlobal
diff --git a/LICENSE b/LICENSE
index 28063e6a..490e1882 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2024 Kate Titova
+Copyright (c) 2025 Kate Titova
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Tests/FunctionsT/FunctionsT.fsproj b/Tests/FunctionsT/FunctionsT.fsproj
new file mode 100644
index 00000000..b448ceba
--- /dev/null
+++ b/Tests/FunctionsT/FunctionsT.fsproj
@@ -0,0 +1,27 @@
+
+
+
+ net8.0
+
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/FunctionsT/Program.fs b/Tests/FunctionsT/Program.fs
new file mode 100644
index 00000000..fdc31cde
--- /dev/null
+++ b/Tests/FunctionsT/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/Tests/UnitTestsFunctions.fs b/Tests/FunctionsT/UnitFunctions.fs
similarity index 82%
rename from Tests/UnitTestsFunctions.fs
rename to Tests/FunctionsT/UnitFunctions.fs
index 5278c26b..009d3ada 100644
--- a/Tests/UnitTestsFunctions.fs
+++ b/Tests/FunctionsT/UnitFunctions.fs
@@ -1,52 +1,52 @@
-namespace UnitTestsFunctions
-
-open System
-open Microsoft.VisualStudio.TestTools.UnitTesting
-
-open Functions.Factorial
-open Functions.Fibinacci
-
-
-[]
-
-type FactorialTests() =
-
- [] // 0!
- member this.testFactorialZero() = Assert.AreEqual(1, factorial (0))
-
- [] // 1!
- member this.testFactorialOne() = Assert.AreEqual(1, factorial (1))
-
- [] // 5!
- member this.testFactorialFive() = Assert.AreEqual(120, factorial (5))
-
- [] // (-1)!
- member this.testFactorialNegative() =
- let ex = Assert.ThrowsException(fun () -> factorial -1 :> obj)
- Assert.AreEqual("The factorial of negative numbers is not calculated by this program\n", ex.Message)
-
-
-[]
-
-type FibinacciMatrixTests() =
-
- [] // F0
- member this.fibZero() = Assert.AreEqual(0L, fibonacci (0))
-
- [] // F1
- member this.fibOne() = Assert.AreEqual(1L, fibonacci (1))
-
- [] // F2
- member this.fibTwo() = Assert.AreEqual(1L, fibonacci (2))
-
- [] // F3
- member this.fibThree() = Assert.AreEqual(2L, fibonacci (3))
-
- [] // F30
- member this.fibThreety() =
- Assert.AreEqual(832040L, fibonacci (30))
-
- [] // F(-1)
- member this.fibNegative() =
- let ex = Assert.ThrowsException(fun () -> fibonacci -1 :> obj)
- Assert.AreEqual("Fibonacci numbers for negative n are not defined\n", ex.Message)
+namespace UnitTestsFunctions
+
+open System
+open Microsoft.VisualStudio.TestTools.UnitTesting
+
+open Functions.Factorial
+open Functions.Fibinacci
+
+
+[]
+
+type FactorialTests() =
+
+ []
+ member this.testFactorialZero() = Assert.AreEqual(1, factorial (0))
+
+ []
+ member this.testFactorialOne() = Assert.AreEqual(1, factorial (1))
+
+ []
+ member this.testFactorialFive() = Assert.AreEqual(120, factorial (5))
+
+ []
+ member this.testFactorialNegative() =
+ let ex = Assert.ThrowsException(fun () -> factorial -1 :> obj)
+ Assert.AreEqual("The factorial of negative numbers is not calculated by this program\n", ex.Message)
+
+
+[]
+
+type FibinacciMatrixTests() =
+
+ []
+ member this.fibZero() = Assert.AreEqual(0L, fibonacci (0))
+
+ []
+ member this.fibOne() = Assert.AreEqual(1L, fibonacci (1))
+
+ []
+ member this.fibTwo() = Assert.AreEqual(1L, fibonacci (2))
+
+ []
+ member this.fibThree() = Assert.AreEqual(2L, fibonacci (3))
+
+ []
+ member this.fibThreety() =
+ Assert.AreEqual(832040L, fibonacci (30))
+
+ []
+ member this.fibNegative() =
+ let ex = Assert.ThrowsException(fun () -> fibonacci -1 :> obj)
+ Assert.AreEqual("Fibonacci numbers for negative n are not defined\n", ex.Message)
diff --git a/Tests/GraphsT/DataAndFuncs.fs b/Tests/GraphsT/DataAndFuncs.fs
new file mode 100644
index 00000000..c3d644ef
--- /dev/null
+++ b/Tests/GraphsT/DataAndFuncs.fs
@@ -0,0 +1,132 @@
+namespace DataAndFuncs
+
+open System
+open System.Collections.Generic
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+open FsCheck.FSharp
+open LineralAlgebra
+
+open Graphs
+
+
+module Data =
+ let leaf = Leaf (Some [|1|])
+ let gLeaf1 = { n = 1; qtree = leaf }
+ let gLeaf4 = { n = 4; qtree = leaf }
+
+ let leafArr = Leaf (Some [|1; 2; 3|])
+ let gLeafArr1 = { n = 1; qtree = leafArr }
+ let gLeafArr4 = { n = 4; qtree = leafArr }
+
+ let node = Node (
+ Node ( Leaf None, Leaf (Some [|1|]), Leaf (Some [|1; 2|]), Leaf (Some [|3|])),
+ Node ( Leaf (Some [|4; 5|]), Leaf (Some [|6|]), Leaf (Some [|7; 8|]), Leaf (Some [|9|])),
+ Leaf (Some [|10|]),
+ Node ( Leaf (Some [|11|]), Leaf (Some [|12|]), Leaf (Some [|13|]), Leaf (Some [|14|]))
+ )
+ let gNode = { n = 4; qtree = node }
+
+ let zeroGraph = { n = 4; qtree = Leaf None }
+ let fullGraph = { n = 4; qtree = Leaf (Some [|1|])}
+
+ let node1 = Node (
+ Leaf None,
+ Leaf (Some [|'a'|]),
+ Leaf None,
+ Leaf None
+ )
+ let graph1 = { n = 2; qtree = node1 }
+ let node2 = Node (
+ Node ( Leaf None, Leaf (Some [|true|]), Leaf None, Leaf None),
+ Node ( Leaf None, Leaf None, Leaf (Some [|true|]), Leaf None),
+ Leaf None,
+ Node ( Leaf None, Leaf (Some [|true|]), Leaf None, Leaf None)
+ )
+ let graph2 = { n = 4; qtree = node2 }
+
+
+module Generator =
+ let GraphGen size typeOfMatr =
+ let LeafGen =
+ let someOrNone = Random().Next(0, 1)
+ if someOrNone = 0 then Leaf None
+ else
+ let size = Random().Next(1, 10)
+ let array = Array.zeroCreate size
+ for i in 0 .. size - 1 do
+ array.[i] <- Random().Next(-100, 10)
+
+ Leaf (Some array)
+
+ let rec QTreeGen size typeOfMatr =
+ if size = 1 then
+ match typeOfMatr with
+ | "Leaf" -> LeafGen
+ | "Node" -> LeafGen
+ | _ -> failwith "Not Implemented"
+ else
+ let nw = QTreeGen (size / 2) typeOfMatr
+ let ne = QTreeGen (size / 2) typeOfMatr
+ let sw = QTreeGen (size / 2) typeOfMatr
+ let se = QTreeGen (size / 2) typeOfMatr
+ Node (nw, ne, sw, se)
+
+ let MatrGen (size: int) =
+ let qtree = QTreeGen size typeOfMatr
+ { n = size; qtree = QTrees.toCorrectQTree qtree }
+
+ let res = MatrGen size
+ res
+
+
+module Funcs =
+ let toAdjacencyMatrix (graph: Matrix>) =
+ let func (value: Edjes<'t>) =
+ match value with
+ | Some _ -> 1
+ | None -> 0
+ let res = Matrix.map func graph
+ res
+
+ let rec getElOfQTree (qtree: QTree>) =
+ let handleLeaf edjes =
+ match edjes with
+ | None ->
+ Unchecked.defaultof<'t>
+ | Some array ->
+ Array.min array
+
+ match qtree with
+ | Leaf edjes -> handleLeaf edjes
+ | Node(_, _, _, _) -> failwith "Not Implemented"
+
+ let rec findValue (qtree: QTree<'t>) (size: int) i j : 't =
+ match qtree with
+ | Leaf value -> value
+ | Node(nw, ne, sw, se) ->
+ if i < size / 2 && j < size / 2 then
+ findValue nw (size / 2) i j
+ elif i < size / 2 && j >= size / 2 then
+ findValue ne (size / 2) i (j - size / 2)
+ elif i >= size / 2 && j < size / 2 then
+ findValue sw (size / 2) (i - size / 2) j
+ else
+ findValue se (size / 2) (i - size / 2) (j - size / 2)
+
+ let transitiveClosureMatrices (matrix: int array2d) =
+ if matrix = null then
+ Array2D.create 0 0 0
+ else
+ let rows = Array2D.length1 matrix
+ let res = Array2D.copy matrix
+
+ for k in 0 .. rows - 1 do
+ for i in 0 .. rows - 1 do
+ for j in 0 .. rows - 1 do
+ if res.[i,k] = 1 && res.[k,j] = 1 then
+ res.[i,j] <- 1
+ else
+ res.[i,j] <- max res.[i,j] res.[i,k] * res.[k,j]
+ res
\ No newline at end of file
diff --git a/Tests/GraphsT/GraphsT.fsproj b/Tests/GraphsT/GraphsT.fsproj
new file mode 100644
index 00000000..7969a62f
--- /dev/null
+++ b/Tests/GraphsT/GraphsT.fsproj
@@ -0,0 +1,32 @@
+
+
+
+ net8.0
+
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/GraphsT/Program.fs b/Tests/GraphsT/Program.fs
new file mode 100644
index 00000000..0695f84c
--- /dev/null
+++ b/Tests/GraphsT/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/Tests/GraphsT/PropertyGraphs.fs b/Tests/GraphsT/PropertyGraphs.fs
new file mode 100644
index 00000000..c3a0078b
--- /dev/null
+++ b/Tests/GraphsT/PropertyGraphs.fs
@@ -0,0 +1,70 @@
+namespace PropertyGraphs
+
+open System
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+open FsCheck.FSharp
+open LineralAlgebra
+
+open Graphs
+open Graphs.Graphs
+open DataAndFuncs.Generator
+open DataAndFuncs.Funcs
+
+
+[]
+type ShortestWay() =
+
+ let power = Random().Next(1, 3)
+ let size = pown 2 power
+
+ []
+ member _.leaf1 () =
+ let graph = GraphGen 1 "Leaf"
+ let res = shortestWay graph 0 0 Array.min
+ let ex = getElOfQTree graph.qtree
+ Assert.Equal(ex, res)
+
+ []
+ member _.leafSize () =
+ let graph = GraphGen size "Leaf"
+ let res = shortestWay graph 0 1 Array.min
+ let ex = getElOfQTree graph.qtree
+ Assert.Equal(ex, res)
+
+ []
+ member _.node () =
+ let graph = GraphGen size "Node"
+ let res = Array2D.zeroCreate size size
+ for i in 0 .. size - 1 do
+ for j in 0 .. size - 1 do
+ res.[i, j] <- shortestWay graph i j Array.min
+
+ let graphArray2D = QTrees.qtreeToArray2D graph.qtree graph.n
+
+ let ex = Array2D.zeroCreate size size
+ for i in 0 .. size - 1 do
+ for j in 0 .. size - 1 do
+ match graphArray2D.[i, j] with
+ | Some array -> ex.[i, j] <- Array.min array
+ | None -> ex.[i, j] <- 0
+ Assert.Equal(ex, res)
+
+
+[]
+type TransitiveClosure() =
+ let power = Random().Next(1, 3)
+ let size = pown 2 power
+
+ []
+ member _.trClosure () =
+ let generatedGraph = GraphGen size "Node"
+ let generatedGraphTrCl = transitiveClosure generatedGraph
+ let resArray = QTrees.qtreeToArray2D generatedGraphTrCl.qtree generatedGraph.n
+
+ let generatedGraphToAdjM = toAdjacencyMatrix generatedGraph
+ let adjMto2Darray = QTrees.qtreeToArray2D generatedGraphToAdjM.qtree generatedGraphToAdjM.n
+
+ let arrayTrCl = transitiveClosureMatrices adjMto2Darray
+ Assert.Equal(arrayTrCl, resArray)
\ No newline at end of file
diff --git a/Tests/GraphsT/UnitGraphs.fs b/Tests/GraphsT/UnitGraphs.fs
new file mode 100644
index 00000000..82fa466d
--- /dev/null
+++ b/Tests/GraphsT/UnitGraphs.fs
@@ -0,0 +1,101 @@
+namespace UnitGraphs
+
+open System
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+open FsCheck.FSharp
+open LineralAlgebra
+
+open Graphs.Graphs
+open DataAndFuncs.Data
+
+
+module ShortestWay =
+
+ []
+ let leaf () =
+ let res = shortestWay gLeaf1 0 0 Array.min
+ let ex = 1
+ Assert.Equal(ex, res)
+
+ []
+ let leaf4 () =
+ let res = shortestWay gLeaf4 0 1 Array.min
+ let ex = 1
+ Assert.Equal(ex, res)
+
+ []
+ let leafArr () =
+ let res = shortestWay gLeafArr1 0 0 Array.min
+ let ex = 1
+ Assert.Equal(ex, res)
+
+ []
+ let leafArr4 () =
+ let res = shortestWay gLeafArr4 1 0 Array.min
+ let ex = 1
+ Assert.Equal(ex, res)
+
+ []
+ let node () =
+ let res = Array2D.zeroCreate 4 4
+ for i in 0 .. 3 do
+ for j in 0 .. 3 do
+ res.[i, j] <- shortestWay gNode i j Array.min
+
+ let arrayArray =
+ [|
+ [|0; 1; 4; 6|];
+ [|1; 3; 7; 9|];
+ [|10; 10; 11; 12|];
+ [|10; 10; 13; 14|]
+ |]
+
+ let ex = Array2D.init 4 4 (fun i j ->
+ if j < arrayArray.[i].Length then
+ arrayArray.[i].[j]
+ else
+ 0
+ )
+
+ Assert.Equal(ex, res)
+
+
+module TransitiveClosure =
+
+ []
+ let zeroGraph () =
+ let res = transitiveClosure zeroGraph
+ let ex = { n = 4; qtree = Leaf 0 }
+ Assert.Equal(ex, res)
+
+ []
+ let fullGraph () =
+ let res = transitiveClosure fullGraph
+ let ex = { n = 4; qtree = Leaf 1 }
+ Assert.Equal(ex, res)
+
+ []
+ let graph2x2 () =
+ let res = transitiveClosure graph1
+ let node = Node (
+ Leaf 0,
+ Leaf 1,
+ Leaf 0,
+ Leaf 0
+ )
+ let ex = { n = 2; qtree = node }
+ Assert.Equal(ex, res)
+
+ []
+ let graph4x4 () =
+ let res = transitiveClosure graph2
+ let node = Node (
+ Node ( Leaf 0, Leaf 1, Leaf 0, Leaf 0),
+ Leaf 1,
+ Leaf 0,
+ Node ( Leaf 0, Leaf 1, Leaf 0, Leaf 0)
+ )
+ let ex = { n = 4; qtree = node }
+ Assert.Equal(ex, res)
\ No newline at end of file
diff --git a/Tests/ImageProcessingT/ImageProcessingT.fsproj b/Tests/ImageProcessingT/ImageProcessingT.fsproj
new file mode 100644
index 00000000..54626247
--- /dev/null
+++ b/Tests/ImageProcessingT/ImageProcessingT.fsproj
@@ -0,0 +1,30 @@
+
+
+
+ net8.0
+
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/ImageProcessingT/Images/id.png b/Tests/ImageProcessingT/Images/id.png
new file mode 100644
index 00000000..d270290e
Binary files /dev/null and b/Tests/ImageProcessingT/Images/id.png differ
diff --git a/Tests/ImageProcessingT/Images/image1.png b/Tests/ImageProcessingT/Images/image1.png
new file mode 100644
index 00000000..8828a550
Binary files /dev/null and b/Tests/ImageProcessingT/Images/image1.png differ
diff --git a/Tests/ImageProcessingT/Images/image2x2px.png b/Tests/ImageProcessingT/Images/image2x2px.png
new file mode 100644
index 00000000..5d286d9d
Binary files /dev/null and b/Tests/ImageProcessingT/Images/image2x2px.png differ
diff --git a/Tests/ImageProcessingT/Images/kernel.png b/Tests/ImageProcessingT/Images/kernel.png
new file mode 100644
index 00000000..ecca06c3
Binary files /dev/null and b/Tests/ImageProcessingT/Images/kernel.png differ
diff --git a/Tests/ImageProcessingT/Images/kernelExtended.png b/Tests/ImageProcessingT/Images/kernelExtended.png
new file mode 100644
index 00000000..ecca06c3
Binary files /dev/null and b/Tests/ImageProcessingT/Images/kernelExtended.png differ
diff --git a/Tests/ImageProcessingT/Images/shiftDiagonal.png b/Tests/ImageProcessingT/Images/shiftDiagonal.png
new file mode 100644
index 00000000..beab1f2f
Binary files /dev/null and b/Tests/ImageProcessingT/Images/shiftDiagonal.png differ
diff --git a/Tests/ImageProcessingT/Images/shiftDownRight.png b/Tests/ImageProcessingT/Images/shiftDownRight.png
new file mode 100644
index 00000000..beab1f2f
Binary files /dev/null and b/Tests/ImageProcessingT/Images/shiftDownRight.png differ
diff --git a/Tests/ImageProcessingT/Images/shiftRightDown.png b/Tests/ImageProcessingT/Images/shiftRightDown.png
new file mode 100644
index 00000000..beab1f2f
Binary files /dev/null and b/Tests/ImageProcessingT/Images/shiftRightDown.png differ
diff --git a/Tests/ImageProcessingT/Program.fs b/Tests/ImageProcessingT/Program.fs
new file mode 100644
index 00000000..fdc31cde
--- /dev/null
+++ b/Tests/ImageProcessingT/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/Tests/ImageProcessingT/PropertyImageProcessing.fs b/Tests/ImageProcessingT/PropertyImageProcessing.fs
new file mode 100644
index 00000000..32d65918
--- /dev/null
+++ b/Tests/ImageProcessingT/PropertyImageProcessing.fs
@@ -0,0 +1,76 @@
+namespace PropertyImageProcessing
+
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+open SixLabors.ImageSharp.PixelFormats
+
+open ImageProcessing.ImProcessing
+open UnitImageProcessing.Data
+
+
+module ImageGen =
+ let private pixelGen : Gen =
+ gen {
+ let! r = Gen.choose(0, 255) |> Gen.map byte
+ let! g = Gen.choose(0, 255) |> Gen.map byte
+ let! b = Gen.choose(0, 255) |> Gen.map byte
+ let a = byte 255
+ return Rgba32(r, g, b, a)
+ }
+ let array2DGen (size: int) : Gen =
+ gen {
+ let! pixels = Gen.array2DOfDim (size, size) pixelGen
+ return pixels
+ }
+
+type Image100() =
+ static member Rgba32() =
+ Arb.fromGen (ImageGen.array2DGen 100)
+
+type Image2() =
+ static member Rgba32() =
+ Arb.fromGen (ImageGen.array2DGen 2)
+
+
+[]
+type Filter() =
+
+ [ |])>]
+ member _.filterDoesntChangeSize (image: Rgba32[,]) =
+ let imageAfterFilter = applyFilter gaussianBlur image
+ Assert.Equal(100, imageAfterFilter.GetLength(0))
+ Assert.Equal(100, imageAfterFilter.GetLength(1))
+
+ [ |])>]
+ member _.idDoesntChangeData (image: Rgba32[,]) =
+ let imageAfterFilter = applyFilter id image
+ Assert.Equal(image, imageAfterFilter)
+
+ [ |])>]
+ member _.imageSmallerThanFilter (image: Rgba32[,]) =
+ let imageAfterFilter = applyFilter black image
+ Assert.Equal(true, imageIsBlack imageAfterFilter)
+
+ [ |])>]
+ member _.blackFilter (image: Rgba32[,]) =
+ let imageBlack = applyFilter black image
+ Assert.Equal(true, imageIsBlack imageBlack)
+
+ [ |])>]
+ member _.shiftComposition (image: Rgba32[,]) =
+ let trivial1and2 = applyFilter shiftRight image |> applyFilter shiftDown
+ let trivial12 = applyFilter shiftDiagonal image
+ Assert.Equal(trivial1and2, trivial12)
+
+ [ |])>]
+ member _.extendedComposition (image: Rgba32[,]) =
+ let imageAfterFilter = applyFilter kernel image
+ let imageAfterExtendedFilter = applyFilter kernelExtended image
+ Assert.Equal(imageAfterFilter, imageAfterExtendedFilter)
+
+ [ |])>]
+ member _.someAreCommutative (image: Rgba32[,]) =
+ let image12 = applyFilter shiftRight image |> applyFilter shiftDown
+ let image21 = applyFilter shiftDown image |> applyFilter shiftRight
+ Assert.Equal(image12, image21)
\ No newline at end of file
diff --git a/Tests/ImageProcessingT/UnitImageProcessing.fs b/Tests/ImageProcessingT/UnitImageProcessing.fs
new file mode 100644
index 00000000..73880dc0
--- /dev/null
+++ b/Tests/ImageProcessingT/UnitImageProcessing.fs
@@ -0,0 +1,134 @@
+namespace UnitImageProcessing
+
+open Xunit
+open SixLabors.ImageSharp.PixelFormats
+
+open ImageProcessing.ImProcessing
+
+
+module Data =
+
+ let im1 = "../../../Images/image1.png"
+ let imSmall = "../../../Images/image2x2px.png"
+ let image1 = loadAsRgba2D im1
+ let imageSmall = loadAsRgba2D imSmall
+
+ let imId = "../../../Images/id.png"
+ let imShiftRightDown = "../../../Images/shiftRightDown.png"
+ let imShiftDownRight = "../../../Images/shiftDownRight.png"
+ let imShiftDiagonal = "../../../Images/shiftDiagonal.png"
+ let imKernel = "../../../Images/kernel.png"
+ let imKernelExtended = "../../../Images/kernelExtended.png"
+ let imageId= loadAsRgba2D imId
+ let imageShiftRightDown= loadAsRgba2D imShiftRightDown
+ let imageShiftDownRight= loadAsRgba2D imShiftDownRight
+ let imageShiftDiagonal= loadAsRgba2D imShiftDiagonal
+ let imageKernel= loadAsRgba2D imKernel
+ let imageKernelExtended= loadAsRgba2D imKernelExtended
+
+
+ let id =
+ [|
+ [| 0; 0; 0 |]
+ [| 0; 1; 0 |]
+ [| 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let black =
+ [|
+ [| 0; 0; 0 |]
+ [| 0; 0; 0 |]
+ [| 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let shiftRight =
+ [|
+ [| 0; 0; 0 |]
+ [| 0; 0; 1 |]
+ [| 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let shiftDown =
+ [|
+ [| 0; 0; 0 |]
+ [| 0; 0; 0 |]
+ [| 0; 1; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let shiftDiagonal =
+ [|
+ [| 0; 0; 0 |]
+ [| 0; 0; 0 |]
+ [| 0; 0; 1 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let kernel =
+ [|
+ [| 1; 1; 1 |]
+ [| 1; -7; 1 |]
+ [| 1; 1; 1 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let kernelExtended =
+ [|
+ [| 0; 0; 0; 0; 0 |]
+ [| 0; 1; 1; 1; 0 |]
+ [| 0; 1; -7; 1; 0 |]
+ [| 0; 1; 1; 1; 0 |]
+ [| 0; 0; 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+
+ let imageIsBlack (image: Rgba32[,]) =
+ let h = image.GetLength 0
+ let w = image.GetLength 1
+
+ let mutable isBlack = true
+
+ for i in 0 .. h - 1 do
+ for j in 0 .. w - 1 do
+ let pixel = image.[i, j]
+ if pixel <> Rgba32(byte 0, byte 0, byte 0, byte 255) then
+ isBlack <- false
+
+ isBlack
+
+
+module Filter =
+ open Data
+
+ []
+ let idDoesntChangeData () =
+ let imageAfterFilter = applyFilter id image1
+ Assert.Equal(imageId, imageAfterFilter)
+
+ []
+ let shiftComposition () =
+ let shiftRightDown = applyFilter shiftRight image1 |> applyFilter shiftDown
+ let shiftDiagonal = applyFilter shiftDiagonal image1
+ Assert.Equal(imageShiftRightDown, imageShiftDiagonal)
+ Assert.Equal(imageShiftRightDown, shiftRightDown)
+ Assert.Equal(imageShiftRightDown, shiftDiagonal)
+
+ []
+ let extendedComposition () =
+ let kernel = applyFilter kernel image1
+ let kernelExtended = applyFilter kernelExtended image1
+ Assert.Equal(imageKernel, imageKernelExtended)
+ Assert.Equal(imageKernel, kernel)
+ Assert.Equal(imageKernel, kernelExtended)
+
+ []
+ let someAreCommutative () =
+ let imageRD = applyFilter shiftRight image1 |> applyFilter shiftDown
+ let imageDR = applyFilter shiftDown image1 |> applyFilter shiftRight
+ Assert.Equal(imageShiftDownRight, imageShiftRightDown)
+ Assert.Equal(imageShiftDownRight, imageDR)
+ Assert.Equal(imageShiftDownRight, imageRD)
\ No newline at end of file
diff --git a/Tests/LineralAlgebraT/LineralAlgebraT.fsproj b/Tests/LineralAlgebraT/LineralAlgebraT.fsproj
new file mode 100644
index 00000000..d2724295
--- /dev/null
+++ b/Tests/LineralAlgebraT/LineralAlgebraT.fsproj
@@ -0,0 +1,34 @@
+
+
+
+ net8.0
+
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/LineralAlgebraT/Program.fs b/Tests/LineralAlgebraT/Program.fs
new file mode 100644
index 00000000..fdc31cde
--- /dev/null
+++ b/Tests/LineralAlgebraT/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/Tests/LineralAlgebraT/PropertyLA.fs b/Tests/LineralAlgebraT/PropertyLA.fs
new file mode 100644
index 00000000..ec5c0052
--- /dev/null
+++ b/Tests/LineralAlgebraT/PropertyLA.fs
@@ -0,0 +1,164 @@
+#nowarn "64"
+
+namespace PropertyLA
+
+open System
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+open FsCheck.FSharp
+
+open LineralAlgebra
+open UnitTrees.dataAndFuncs
+
+
+module DataAndFuncs =
+
+ let rec floatQTreesAreEqual (qtree1: QTree) (qtree2: QTree) : bool =
+ match qtree1, qtree2 with
+ | Node (nw, ne, se, sw), Node (NW, NE, SE, SW) ->
+ floatQTreesAreEqual nw NW &&
+ floatQTreesAreEqual ne NE &&
+ floatQTreesAreEqual se SE &&
+ floatQTreesAreEqual sw SW
+ | Leaf value1, Leaf value2 ->
+ areAlmostEqual value1 value2 1e-5f
+ | _ -> false
+
+ let multiplyArray2D (arr1: 't[,]) (arr2: 't[,]) : 't[,] =
+ let rows1 = Array2D.length1 arr1
+ let cols1 = Array2D.length2 arr1
+ let rows2 = Array2D.length1 arr2
+ let cols2 = Array2D.length2 arr2
+
+ if cols1 <> rows2 then
+ failwith "Number of columns in the first array must match the number of rows in the second array."
+
+ let result = Array2D.create rows1 cols2 Unchecked.defaultof<'t>
+
+ for i in 0 .. rows1 - 1 do
+ for j in 0 .. cols2 - 1 do
+ for k in 0 .. cols1 - 1 do
+ result.[i, j] <- result.[i, j] + arr1.[i, k] * arr2.[k, j]
+
+ result
+
+
+ let MatrixGen size typeOfMatr =
+ let rec QTreeGen size typeOfMatr : QTree =
+ if size = 1 then
+ match typeOfMatr with
+ | "Leaf" ->
+ let value = Random().Next(-100, 101)
+ Leaf value
+ | "Node" ->
+ let value = Random().Next(-100, 101)
+ Leaf value
+ | "Zero" ->
+ let value = 0
+ Leaf value
+ | _ -> failwith "Not Implemented"
+ else
+ let nw = QTreeGen (size / 2) typeOfMatr
+ let ne = QTreeGen (size / 2) typeOfMatr
+ let sw = QTreeGen (size / 2) typeOfMatr
+ let se = QTreeGen (size / 2) typeOfMatr
+ Node (nw, ne, sw, se)
+
+ let MatrGen (size: int) =
+ let qtree = QTreeGen size typeOfMatr
+ { n = size; qtree = QTrees.toCorrectQTree qtree }
+
+ let res = MatrGen size
+ res
+
+
+open DataAndFuncs
+
+[]
+type Map() =
+
+ []
+ member _.intId (qtree: QTree) =
+ qtree |> QTrees.toCorrectQTree = QTrees.map id qtree
+
+ []
+ member _.floatId (qtree: QTree) =
+ let res = QTrees.map id qtree
+ Assert.True(floatQTreesAreEqual (qtree |> QTrees.toCorrectQTree) res)
+
+
+ []
+ member _.intComposition (qtree: QTree) =
+ let qtree1 = QTrees.map ((+) 1)((QTrees.map ((+) 2)) qtree)
+ let qtree2 = QTrees.map ((+) 3) qtree
+ qtree1 = qtree2
+
+ []
+ member _.floatComposition (qtree: QTree) =
+ let qtree1 = QTrees.map ((+) 1.0f) (QTrees.map ((+) 2.0f) qtree)
+ let qtree2 = QTrees.map ((+) 3.0f) qtree
+ Assert.True(floatQTreesAreEqual qtree1 qtree2)
+
+
+ []
+ member _.intHighIsConst (qtree: QTree) =
+ let h1 = QTrees.height (qtree |> QTrees.toCorrectQTree)
+ let h2 = QTrees.height (QTrees.map ((+) 1) qtree)
+ h1 = h2
+
+
+[]
+type Multiply() =
+
+ let power = Random().Next(1, 6)
+ let size = pown 2 power
+
+ []
+ member _.leafLeaf () =
+ let matr1 = MatrixGen 1 "Leaf"
+ let matr2 = MatrixGen 1 "Leaf"
+ let res = Matrix.multiply matr1 matr2 (+) ( * ) 0
+ let arrayRess = QTrees.qtreeToArray2D res.qtree res.n
+ let arrayEx = multiplyArray2D (QTrees.qtreeToArray2D matr1.qtree matr1.n) (QTrees.qtreeToArray2D matr2.qtree matr2.n)
+ Assert.Equal(arrayEx, arrayRess)
+
+ []
+ member _.nodeLeaf () =
+ let matr1 = MatrixGen size "Node"
+ let matr2 = MatrixGen size "Leaf"
+ let res = Matrix.multiply matr1 matr2 (+) ( * ) 0
+ let arrayRess = QTrees.qtreeToArray2D res.qtree res.n
+ let arrayEx = multiplyArray2D (QTrees.qtreeToArray2D matr1.qtree matr1.n) (QTrees.qtreeToArray2D matr2.qtree matr2.n)
+ Assert.Equal(arrayEx, arrayRess)
+
+ []
+ member _.leafNode () =
+ let matr1 = MatrixGen size "Leaf"
+ let matr2 = MatrixGen size "Node"
+ let res = Matrix.multiply matr1 matr2 (+) ( * ) 0
+ let arrayRess = QTrees.qtreeToArray2D res.qtree res.n
+ let arrayEx = multiplyArray2D (QTrees.qtreeToArray2D matr1.qtree matr1.n) (QTrees.qtreeToArray2D matr2.qtree matr2.n)
+ Assert.Equal(arrayEx, arrayRess)
+
+ []
+ member _.nodeNode () =
+ let matr1 = MatrixGen size "Node"
+ let matr2 = MatrixGen size "Node"
+ let res = Matrix.multiply matr1 matr2 (+) ( * ) 0
+ let arrayRess = QTrees.qtreeToArray2D res.qtree res.n
+ let arrayEx = multiplyArray2D (QTrees.qtreeToArray2D matr1.qtree matr1.n) (QTrees.qtreeToArray2D matr2.qtree matr2.n)
+ Assert.Equal(arrayEx, arrayRess)
+
+ []
+ member _.zero () =
+ let matr1 = MatrixGen size "Zero"
+ let matr2 = MatrixGen size "Node"
+ let res = Matrix.multiply matr1 matr2 (+) ( * ) 0
+ let arrayRess = QTrees.qtreeToArray2D res.qtree res.n
+ let res1 = Matrix.multiply matr2 matr1 (+) ( * ) 0
+ let arrayRess1 = QTrees.qtreeToArray2D res1.qtree res1.n
+
+ let arrayEx = multiplyArray2D (QTrees.qtreeToArray2D matr1.qtree matr1.n) (QTrees.qtreeToArray2D matr2.qtree matr2.n)
+ Assert.Equal(arrayEx, arrayRess)
+ Assert.Equal(arrayEx, arrayRess1)
\ No newline at end of file
diff --git a/Tests/LineralAlgebraT/UnitLA.fs b/Tests/LineralAlgebraT/UnitLA.fs
new file mode 100644
index 00000000..a0f77d81
--- /dev/null
+++ b/Tests/LineralAlgebraT/UnitLA.fs
@@ -0,0 +1,341 @@
+namespace UnitLA
+
+open System
+open Xunit
+
+open LineralAlgebra
+
+
+module DataAndFuncs =
+
+ let intOneLeaf1 = Leaf 1
+ let MintOneLeaf1 = { n = 4; qtree = intOneLeaf1 }
+
+ let intOneLeaf2 = Leaf 2
+
+ let intOneLeaf3 = Leaf 2
+ let MintOneLeaf3 = { n = 1; qtree = intOneLeaf3 }
+
+ let intOneLeaf4 = Leaf 3
+ let MintOneLeaf4 = { n = 1; qtree = intOneLeaf4 }
+
+ let intNode1 = Leaf 2
+ let MintNode1 = { n = 2; qtree = intNode1 }
+
+ let intNode2 = Leaf 3
+ let MintNode2 = { n = 2; qtree = intNode2 }
+
+ let intZero = Leaf 0
+ let MintZero = { n = 4; qtree = intZero }
+
+ let floatOneLeaf = Leaf 1.0
+
+ let intQTree1 = Node (
+ Node ( Leaf 1, Leaf 2, Leaf 3, Leaf 4),
+ Node ( Leaf -5, Leaf -6, Leaf -7, Leaf -8),
+ Leaf 9,
+ Node ( Leaf -10, Leaf -11, Leaf -12, Leaf -13)
+ )
+ let MintQTree1 = { n = 4; qtree = intQTree1 }
+
+ let intQTree2 = Node (
+ Node ( Leaf 1, Leaf 2, Leaf 3, Leaf 4),
+ Leaf 5,
+ Leaf 6,
+ Node ( Leaf 7, Leaf 8, Leaf 9, Leaf 10)
+ )
+ let MintQTree2 = { n = 4; qtree = intQTree2 }
+
+ let floatQTree1 = Node (
+ Node ( Leaf 1.0, Leaf 2.0, Leaf 3.0, Leaf 4.0),
+ Node ( Leaf -5.0, Leaf -6.0, Leaf -7.0, Leaf -8.0),
+ Leaf 9.0,
+ Node ( Leaf -10.0, Leaf -11.0, Leaf -12.0, Leaf -13.0)
+ )
+
+ let floatQTree2 = Node (
+ Node ( Leaf 1.0, Leaf 2.0, Leaf 3.0, Leaf 4.0),
+ Leaf 5.0,
+ Leaf 6.0,
+ Node ( Leaf 7.0, Leaf 8.0, Leaf 9.0, Leaf 10.0)
+ )
+
+
+module Map =
+ open DataAndFuncs
+
+ []
+ let intId () =
+ let res = QTrees.map id intQTree1
+ Assert.Equal(intQTree1, res)
+
+ []
+ let floatId () =
+ let res = QTrees.map id floatQTree1
+ Assert.Equal(floatQTree1, res)
+
+
+ []
+ let intAdd () =
+ let res = QTrees.map ((+) 1) intQTree1
+ let ex = Node (
+ Node ( Leaf 2, Leaf 3, Leaf 4, Leaf 5),
+ Node ( Leaf -4, Leaf -5, Leaf -6, Leaf -7),
+ Leaf 10,
+ Node ( Leaf -9, Leaf -10, Leaf -11, Leaf -12)
+ )
+ Assert.Equal(ex, res)
+
+ []
+ let floatAdd () =
+ let res = QTrees.map ((+) 1.0) floatQTree1
+ let ex = Node (
+ Node ( Leaf 2.0, Leaf 3.0, Leaf 4.0, Leaf 5.0),
+ Node ( Leaf -4.0, Leaf -5.0, Leaf -6.0, Leaf -7.0),
+ Leaf 10.0,
+ Node ( Leaf -9.0, Leaf -10.0, Leaf -11.0, Leaf -12.0)
+ )
+ Assert.Equal(ex, res)
+
+
+ []
+ let intMult () =
+ let res = QTrees.map (fun x -> 2 * x) intQTree1
+ let ex = Node (
+ Node ( Leaf 2, Leaf 4, Leaf 6, Leaf 8),
+ Node ( Leaf -10, Leaf -12, Leaf -14, Leaf -16),
+ Leaf 18,
+ Node ( Leaf -20, Leaf -22, Leaf -24, Leaf -26)
+ )
+ Assert.Equal(ex, res)
+
+ []
+ let floatMult () =
+ let res = QTrees.map (fun x -> 2.0 * x) floatQTree1
+ let ex = Node (
+ Node ( Leaf 2.0, Leaf 4.0, Leaf 6.0, Leaf 8.0),
+ Node ( Leaf -10.0, Leaf -12.0, Leaf -14.0, Leaf -16.0),
+ Leaf 18.0,
+ Node ( Leaf -20.0, Leaf -22.0, Leaf -24.0, Leaf -26.0)
+ )
+ Assert.Equal(ex, res)
+
+
+ // functions intSign and floatSign are written to check that nodes with the same leaves are merged into 1 leaf
+
+ []
+ let intSign () =
+ let res = QTrees.map (fun (x: int) -> Math.Sign x) intQTree1
+ let ex = Node (
+ Leaf 1,
+ Leaf -1,
+ Leaf 1,
+ Leaf -1
+ )
+ Assert.Equal(ex, res)
+
+ []
+ let floatSign () =
+ let res = QTrees.map (fun (x: float) -> Math.Sign x) floatQTree1
+ let ex = Node (
+ Leaf 1,
+ Leaf -1,
+ Leaf 1,
+ Leaf -1
+ )
+ Assert.Equal(ex, res)
+
+
+ []
+ let intComposition () =
+ let tree1 = QTrees.map ((+) 1)((QTrees.map ((+) 2)) intQTree1)
+ let tree2 = QTrees.map ((+) 3) intQTree1
+ let ex = Node (
+ Node ( Leaf 4, Leaf 5, Leaf 6, Leaf 7),
+ Node ( Leaf -2, Leaf -3, Leaf -4, Leaf -5),
+ Leaf 12,
+ Node ( Leaf -7, Leaf -8, Leaf -9, Leaf -10)
+ )
+ Assert.Equal(ex, tree1)
+ Assert.Equal(ex, tree2)
+
+ []
+ let floatComposition () =
+ let tree1 = QTrees.map ((+) 1.0) (QTrees.map ((+) 2.0) floatQTree1)
+ let tree2 = QTrees.map ((+) 3.0) floatQTree1
+ let ex = Node (
+ Node ( Leaf 4.0, Leaf 5.0, Leaf 6.0, Leaf 7.0),
+ Node ( Leaf -2.0, Leaf -3.0, Leaf -4.0, Leaf -5.0),
+ Leaf 12.0,
+ Node ( Leaf -7, Leaf -8.0, Leaf -9.0, Leaf -10.0)
+ )
+ Assert.Equal(ex, tree1)
+ Assert.Equal(ex, tree2)
+
+
+ []
+ let intHighIsConst () =
+ let h1 = QTrees.height intQTree1
+ let h2 = QTrees.height (QTrees.map ((+) 1) intQTree1)
+ Assert.Equal(3, h1)
+ Assert.Equal(3, h2)
+
+ []
+ let floatHighIsConst () =
+ let h1 = QTrees.height floatQTree1
+ let h2 = QTrees.height (QTrees.map ((+) 1.0) floatQTree1)
+ Assert.Equal(3, h1)
+ Assert.Equal(3, h2)
+
+
+ (*
+ functions intHighIsExpected and floatHighIsExpected are written to check that
+ when merging nodes into a leaf, the height decreases correctly
+ *)
+
+ []
+ let intHighIsExpected () =
+ let h = QTrees.height (QTrees.map (fun (x: int) -> Math.Sign x) intQTree1)
+ Assert.Equal(2, h)
+
+ []
+ let floatHighIsExpected () =
+ let h = QTrees.height (QTrees.map (fun (x: float) -> Math.Sign x) floatQTree1)
+ Assert.Equal(2, h)
+
+
+module Map2 =
+ open DataAndFuncs
+
+ []
+ let intAdd () =
+ let res = QTrees.map2 (+) intQTree1 intQTree2
+ let ex = Node (
+ Node ( Leaf 2, Leaf 4, Leaf 6, Leaf 8),
+ Node ( Leaf 0, Leaf -1, Leaf -2, Leaf -3),
+ Leaf 15,
+ Leaf -3
+ )
+ Assert.Equal(ex, res)
+
+ []
+ let floatAdd () =
+ let res = QTrees.map2 (+) floatQTree1 floatQTree2
+ let ex = Node (
+ Node ( Leaf 2.0, Leaf 4.0, Leaf 6.0, Leaf 8.0),
+ Node ( Leaf 0.0, Leaf -1.0, Leaf -2.0, Leaf -3.0),
+ Leaf 15.0,
+ Leaf -3.0
+ )
+ Assert.Equal(ex, res)
+
+
+ []
+ let intMult () =
+ let res = QTrees.map2 (fun x y -> x * y) intQTree1 intQTree2
+ let ex = Node (
+ Node ( Leaf 1, Leaf 4, Leaf 9, Leaf 16),
+ Node ( Leaf -25, Leaf -30, Leaf -35, Leaf -40),
+ Leaf 54,
+ Node ( Leaf -70, Leaf -88, Leaf -108, Leaf -130)
+ )
+ Assert.Equal(ex, res)
+
+ []
+ let floatMult () =
+ let res = QTrees.map2 (fun x y -> x * y) floatQTree1 floatQTree2
+ let ex = Node (
+ Node ( Leaf 1.0, Leaf 4.0, Leaf 9.0, Leaf 16.0),
+ Node ( Leaf -25.0, Leaf -30.0, Leaf -35.0, Leaf -40.0),
+ Leaf 54.0,
+ Node ( Leaf -70.0, Leaf -88.0, Leaf -108.0, Leaf -130.0)
+ )
+ Assert.Equal(ex, res)
+
+
+ []
+ let intHighIsExpected () =
+ let h1 = QTrees.height intQTree1
+ let h2 = QTrees.height intOneLeaf1
+ let h3 = max h1 h2
+ let h4 = QTrees.height (QTrees.map2 (+) intQTree1 intOneLeaf1)
+ Assert.Equal(3, h3)
+ Assert.Equal(3, h4)
+
+ []
+ let floatHighIsExpected () =
+ let h1 = QTrees.height floatQTree1
+ let h2 = QTrees.height floatOneLeaf
+ let h3 = max h1 h2
+ let h4 = QTrees.height (QTrees.map2 (+) floatQTree1 floatOneLeaf)
+ Assert.Equal(3, h3)
+ Assert.Equal(3, h4)
+
+
+module Multiply =
+ open DataAndFuncs
+
+ []
+ let sizeIsImportant () =
+ let res1 = Matrix.multiply MintOneLeaf3 MintOneLeaf4 (+) ( * ) 0
+ let ex1 = { n = 1; qtree = Leaf 6 }
+ let res2 = Matrix.multiply MintNode1 MintNode2 (+) ( * ) 0
+ let ex2 = { n = 2; qtree = Leaf 12 }
+ Assert.Equal(ex1, res1)
+ Assert.Equal(ex2, res2)
+
+ []
+ let leafLeaf () =
+ let res = Matrix.multiply MintOneLeaf3 MintOneLeaf4 (+) ( * ) 0
+ let ex = { n = 1; qtree = Leaf 6 }
+ Assert.Equal(ex, res)
+
+ []
+ let nodeLeaf () =
+ let res = Matrix.multiply MintQTree1 MintOneLeaf1 (+) ( * ) 0
+ let ex = {
+ n = 4;
+ qtree = Node (
+ Leaf -8,
+ Leaf -8,
+ Node ( Leaf -3, Leaf -3, Leaf -7, Leaf -7),
+ Node ( Leaf -3, Leaf -3, Leaf -7, Leaf -7)
+ )
+ }
+ Assert.Equal(ex, res)
+
+ []
+ let leafNode () =
+ let res = Matrix.multiply MintOneLeaf1 MintQTree1 (+) ( * ) 0
+ let ex = {
+ n = 4;
+ qtree = Node (
+ Node ( Leaf 22, Leaf 24, Leaf 22, Leaf 24),
+ Node ( Leaf -34, Leaf -38, Leaf -34, Leaf -38),
+ Node ( Leaf 22, Leaf 24, Leaf 22, Leaf 24),
+ Node ( Leaf -34, Leaf -38, Leaf -34, Leaf -38)
+ )
+ }
+ Assert.Equal(ex, res)
+
+ []
+ let nodeNode () =
+ let res = Matrix.multiply MintQTree1 MintQTree2 (+) ( * ) 0
+ let ex = {
+ n = 4;
+ qtree = Node (
+ Node (Leaf -59, Leaf -56, Leaf -75, Leaf -68),
+ Node (Leaf -74, Leaf -85, Leaf -86, Leaf -101),
+ Node (Leaf -90, Leaf -72, Leaf -114, Leaf -96),
+ Node (Leaf -79, Leaf -100, Leaf -111, Leaf -136)
+ )
+ }
+ Assert.Equal(ex, res)
+
+ []
+ let zero () =
+ let res1 = Matrix.multiply MintQTree1 MintZero (+) ( * ) 0
+ let res2 = Matrix.multiply MintZero MintQTree1 (+) ( * ) 0
+ let ex = { n = 4; qtree = Leaf 0 }
+ Assert.Equal(ex, res1)
+ Assert.Equal(ex, res2)
\ No newline at end of file
diff --git a/Tests/Program.fs b/Tests/Program.fs
deleted file mode 100644
index f1bb4ba9..00000000
--- a/Tests/Program.fs
+++ /dev/null
@@ -1,3 +0,0 @@
-module Program =
- []
- let main _ = 0
\ No newline at end of file
diff --git a/Tests/SortingsT/Program.fs b/Tests/SortingsT/Program.fs
new file mode 100644
index 00000000..fdc31cde
--- /dev/null
+++ b/Tests/SortingsT/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/Tests/PropertyTestsMyListSorts.fs b/Tests/SortingsT/PropertyMyListSorts.fs
similarity index 99%
rename from Tests/PropertyTestsMyListSorts.fs
rename to Tests/SortingsT/PropertyMyListSorts.fs
index f7ca8fd7..c0d8e8f6 100644
--- a/Tests/PropertyTestsMyListSorts.fs
+++ b/Tests/SortingsT/PropertyMyListSorts.fs
@@ -142,4 +142,4 @@ type MergeEqualsQuick() =
member _.charTest(testCases: char list) =
let merge = bubbleSort (MyList.fromSystemList testCases) |> MyList.toSystemList
let quick = quickSort (MyList.fromSystemList testCases) |> MyList.toSystemList
- Assert.Equal(merge, quick)
+ Assert.Equal(merge, quick)
\ No newline at end of file
diff --git a/Tests/Tests.fsproj b/Tests/SortingsT/SortingsT.fsproj
similarity index 73%
rename from Tests/Tests.fsproj
rename to Tests/SortingsT/SortingsT.fsproj
index a26f074d..ded21517 100644
--- a/Tests/Tests.fsproj
+++ b/Tests/SortingsT/SortingsT.fsproj
@@ -9,29 +9,28 @@
-
-
-
-
+
+
+
-
+
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
diff --git a/Tests/UnitTestsArraySorts.fs b/Tests/SortingsT/UnitArraySorts.fs
similarity index 100%
rename from Tests/UnitTestsArraySorts.fs
rename to Tests/SortingsT/UnitArraySorts.fs
diff --git a/Tests/UnitTestsMyListSorts.fs b/Tests/SortingsT/UnitMyListSorts.fs
similarity index 100%
rename from Tests/UnitTestsMyListSorts.fs
rename to Tests/SortingsT/UnitMyListSorts.fs
diff --git a/Tests/TreesT/Program.fs b/Tests/TreesT/Program.fs
new file mode 100644
index 00000000..fdc31cde
--- /dev/null
+++ b/Tests/TreesT/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/Tests/TreesT/PropertyTrees.fs b/Tests/TreesT/PropertyTrees.fs
new file mode 100644
index 00000000..8d27e790
--- /dev/null
+++ b/Tests/TreesT/PropertyTrees.fs
@@ -0,0 +1,157 @@
+namespace PropertyTrees
+
+open System
+open Xunit
+open FsCheck
+open FsCheck.Xunit
+
+open Trees
+open Trees.Tree
+open UnitTrees.dataAndFuncs
+
+
+[]
+type mapProp() =
+
+ []
+ member _.intId (tree: Tree) =
+ tree = map id tree
+
+ []
+ member _.floatId (tree: Tree) =
+ let list = leafToList tree
+ let idList = leafToList (map id tree)
+ Assert.True(List.forall2 (fun a b -> areAlmostEqual a b 1e-10f)list idList)
+
+ []
+ member _.charId (tree: Tree) =
+ tree = map id tree
+
+ []
+ member _.arrayId (tree: Tree>) =
+ tree = map id tree
+
+
+ []
+ member _.intListEqTree (tree: Tree) =
+ let list = List.map ((+) 1) (leafToList tree)
+ let treeList = leafToList (map ((+) 1) tree)
+ list = treeList
+
+ []
+ member _.floatListEqTree (tree: Tree) =
+ let list = List.map ((+) 1.0f) (leafToList tree)
+ let treeList = leafToList (map (fun x -> x + 1.0f) tree)
+ Assert.True(List.forall2 (fun a b -> areAlmostEqual a b 1e-10f)list treeList)
+
+ []
+ member _.charListEqTree (tree: Tree) =
+ let list = List.map (char << ((+) 1 << int)) (leafToList tree)
+ let treeList = leafToList (map (fun c -> char (int c + 1)) tree)
+ list = treeList
+
+ []
+ member _.arrayListEqTree (tree: Tree>) =
+ let func list = Array.map (fun x -> x * x) list
+ let list = List.map func (leafToList tree)
+ let treeList = leafToList (map func tree)
+ list = treeList
+
+
+ []
+ member _.intComposition (tree: Tree) =
+ let tree1 = map ((+) 2) (map ((+) 1) tree)
+ let tree2 = map ((+) 3) tree
+ tree1 = tree2
+
+ []
+ member _.floatComposition (tree: Tree) =
+ let tree1 = leafToList (map ((+) 2.0f) (map ((+) 1.0f) tree))
+ let tree2 = leafToList (map ((+) 3.0f) tree )
+ Assert.True(List.forall2 (fun a b -> areAlmostEqual a b 1e-5f) tree1 tree2)
+
+ []
+ member _.charComposition (tree: Tree) =
+ let tree1 = map (char << ((+) 1 << int)) (map (char << ((+) 1 << int)) tree)
+ let tree2 = map (char << ((+) 2 << int)) tree
+ tree1 = tree2
+
+ []
+ member _.arrayComposition (tree: Tree>) =
+ let f array a = Array.map (fun x -> a * x) array
+ let tree1 = map (fun a -> f a 3) (map (fun a -> f a 2) tree)
+ let tree2 = map (fun a -> f a 6) tree
+ tree1 = tree2
+
+
+ []
+ member _.intHighIsConst (tree: Tree) =
+ let h1 = high (map ((+) 3) tree)
+ let h2 = high (map ((+) 5) tree)
+ h1 = h2
+
+ []
+ member _.floatHighIsConst (tree: Tree) =
+ let h1 = high (map ((+) 3.0f) tree)
+ let h2 = high (map ((+) 5.6f) tree)
+ h1 = h2
+
+ []
+ member _.charHighIsConst (tree: Tree) =
+ let h1 = high (map (char << ((+) 1 << int)) tree)
+ let h2 = high (map (char << ((+) 1 << int)) tree)
+ h1 = h2
+
+ []
+ member _.arrayHighIsConst (tree: Tree>) =
+ let f a array = Array.map (fun x -> a * x) array
+ let h1 = high (map (fun a -> f 2 a) tree)
+ let h2 = high (map (fun a -> f 3 a) tree)
+ h1 = h2
+
+
+[]
+type leftRightFold() =
+
+ []
+ member _.intAdd (tree: Tree) =
+ let sumFunc acc value = acc + value
+ let sum1 = foldLeft sumFunc 0 tree
+ let sum2 = foldRight sumFunc 0 tree
+ sum1 = sum2
+
+ []
+ member _.floatAdd (tree: Tree) =
+ let sumFunc acc value = acc + value
+ let sum1 = foldLeft sumFunc 0.0f tree
+ let sum2 = foldRight sumFunc 0.0f tree
+ Assert.Equal(sum1, sum2, 1)
+
+ []
+ member _.charAdd (tree: Tree) =
+ let sumFunc acc value = acc + (int value + 1)
+ let sum1 = foldLeft sumFunc 0 tree
+ let sum2 = foldRight sumFunc 0 tree
+ sum1 = sum2
+
+
+ []
+ member _.intMult (tree: Tree) =
+ let sumFunc acc value = acc * value
+ let sum1 = foldLeft sumFunc 1 tree
+ let sum2 = foldRight sumFunc 1 tree
+ sum1 = sum2
+
+ []
+ member _.floatMult (tree: Tree) =
+ let sumFunc acc value = acc * value
+ let sum1 = foldLeft sumFunc 0.0f tree
+ let sum2 = foldRight sumFunc 0.0f tree
+ Assert.Equal(sum1, sum2, 1)
+
+ []
+ member _.charMult (tree: Tree) =
+ let sumFunc acc value = acc * (int value + 1)
+ let sum1 = foldLeft sumFunc 0 tree
+ let sum2 = foldRight sumFunc 0 tree
+ sum1 = sum2
\ No newline at end of file
diff --git a/Tests/TreesT/TreesT.fsproj b/Tests/TreesT/TreesT.fsproj
new file mode 100644
index 00000000..9da1a97d
--- /dev/null
+++ b/Tests/TreesT/TreesT.fsproj
@@ -0,0 +1,30 @@
+
+
+
+ net8.0
+
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/TreesT/UnitTrees.fs b/Tests/TreesT/UnitTrees.fs
new file mode 100644
index 00000000..0af09ab4
--- /dev/null
+++ b/Tests/TreesT/UnitTrees.fs
@@ -0,0 +1,245 @@
+namespace UnitTrees
+
+open System
+open Xunit
+
+open Trees
+open Trees.Tree
+
+module dataAndFuncs =
+
+ let oneLeaf = Leaf 1
+
+ let intTree =
+ Node(Cons(
+ Node(Cons(
+ Leaf(1),
+ Single (Leaf(2)))
+ ),
+ Single (Node(Single (Leaf(3))))
+ )
+ )
+
+ let floatTree =
+ Node(Cons(
+ Node(Cons(
+ Leaf(1.00f),
+ Single (Leaf(2.00f)))
+ ),
+ Single (Node(Single (Leaf(3.00f))))
+ )
+ )
+
+ let charTree =
+ Node(Cons(
+ Node(Cons(
+ Leaf('a'),
+ Single (Leaf('b')))
+ ),
+ Single (Node(Single (Leaf('c'))))
+ )
+ )
+
+ let arrayTree =
+ Node(Cons(
+ Node(Cons(
+ Leaf([|1; 2; 3|]),
+ Single (Leaf([|5; 0; 0|])))
+ ),
+ Single (Node(Single (Leaf([|2; 3|]))))
+ )
+ )
+
+ let rec leafToList tree =
+ match tree with
+ | Leaf value -> [value]
+ | Node children ->
+ match children with
+ | Single child -> leafToList child
+ | Cons (head, tail) ->
+ leafToList head @ leafToList (Node tail)
+
+ let areAlmostEqual (a: float32) (b: float32) (epsilon: float32) =
+ if Single.IsFinite(a) && Single.IsFinite(b) then abs (a - b) < epsilon
+ elif Single.IsNaN(a) && Single.IsNaN(b) then true
+ elif Single.IsInfinity(a) && Single.IsInfinity(b) then true
+ elif Single.IsNegativeInfinity(a) && Single.IsNegativeInfinity(b) then true
+ elif Single.IsPositiveInfinity(a) && Single.IsPositiveInfinity(b) then true
+ else false
+
+
+module map =
+ open dataAndFuncs
+
+ []
+ let intId () = intTree = map id intTree
+
+ []
+ let floatId () = floatTree = map id floatTree
+
+ []
+ let charId () = charTree = map id charTree
+
+ []
+ let arrayId () = arrayTree = map id arrayTree
+
+
+ []
+ let intListEqTree () =
+ let list = List.map ((+) 1) (leafToList intTree)
+ let treeList = leafToList (map ((+) 1) intTree)
+ let ex = [ 2; 3; 4 ]
+ Assert.Equal(ex, list)
+ Assert.Equal(ex, treeList)
+
+ []
+ let floatListEqTree () =
+ let list = List.map ((+) 1.0f) (leafToList floatTree)
+ let treeList = leafToList (map (fun x -> x + 1.0f) floatTree)
+ let ex = [ 2.00f; 3.00f; 4.00f ]
+ Assert.Equal(ex, list)
+ Assert.Equal(ex, treeList)
+
+ []
+ let charListEqTree () =
+ let list = List.map (char << ((+) 1 << int)) (leafToList charTree)
+ let treeList = leafToList (map (fun c -> char (int c + 1)) charTree)
+ let ex = [ 'b'; 'c'; 'd' ]
+ Assert.Equal(ex, list)
+ Assert.Equal(ex, treeList)
+
+ []
+ let arrayListEqTree () =
+ let func list = Array.map (fun x -> x * x) list
+ let list = List.map func (leafToList arrayTree)
+ let treeList = leafToList (map func arrayTree)
+ let ex = [ [|1; 4; 9|]; [|25; 0; 0|]; [|4; 9|] ]
+ Assert.Equal>(ex, list)
+ Assert.Equal>(ex, treeList)
+
+
+ []
+ let intComposition () =
+ let tree1 = map ((+) 2) (map ((+) 1) intTree)
+ let tree2 = map ((+) 3) intTree
+ let ex = Node(Cons(Node(Cons(Leaf(4), Single (Leaf(5)))), Single (Node(Single (Leaf(6))))))
+ Assert.Equal>(ex, tree1)
+ Assert.Equal>(ex, tree2)
+
+ []
+ let floatComposition () =
+ let tree1 = leafToList (map ((+) 1.00f) (map ((+) 2.00f) floatTree))
+ let tree2 = leafToList (map ((+) 3.00f) floatTree)
+ let ex = leafToList (Node(Cons(Node(Cons(Leaf(4.00f), Single (Leaf(5.00f)))), Single (Node(Single (Leaf(6.00f)))))))
+ Assert.True(List.forall2 (fun e a -> areAlmostEqual e a 1e-10f) ex tree1)
+ Assert.True(List.forall2 (fun e a -> areAlmostEqual e a 1e-10f) ex tree2)
+
+ []
+ let charComposition () =
+ let tree1 = map (char << ((+) 1 << int)) (map (char << ((+) 1 << int)) charTree)
+ let tree2 = map (char << ((+) 2 << int)) charTree
+ let ex = Node(Cons(Node(Cons(Leaf('c'), Single (Leaf('d')))), Single (Node(Single (Leaf('e'))))))
+ Assert.Equal>(ex, tree1)
+ Assert.Equal>(ex, tree2)
+
+ []
+ let arrayComposition () =
+ let f list a = Array.map (fun x -> a * x) list
+ let tree1 = map (fun a -> f a 3) (map (fun a -> f a 2) arrayTree)
+ let tree2 = map (fun a -> f a 6) arrayTree
+ let ex = Node(Cons(Node(Cons(Leaf([|6; 12; 18|]), Single (Leaf([|30; 0; 0|])))), Single (Node(Single (Leaf([|12; 18|]))))))
+ Assert.Equal>>(ex, tree1)
+ Assert.Equal>>(ex, tree2)
+
+
+ []
+ let intHighIsConst () =
+ let h = high (map ((+) 3) intTree)
+ Assert.Equal(3, h)
+
+ []
+ let floatHighIsConst () =
+ let h = high (map ((+) 3.0f) floatTree)
+ Assert.Equal(3, h)
+
+ []
+ let charHighIsConst () =
+ let h = high (map (char << ((+) 1 << int)) charTree)
+ Assert.Equal(3, h)
+
+ []
+ let arrayHighIsConst () =
+ let f a list = Array.map (fun x -> a * x) list
+ let h = high (map (fun a -> f 2 ) arrayTree)
+ Assert.Equal(3, h)
+
+
+module AssociativeFolds =
+ open dataAndFuncs
+
+ []
+ let intAdd () =
+ let sumFunc value acc = acc + value
+ let sum1 = foldLeft sumFunc 0 intTree
+ let sum2 = foldRight sumFunc 0 intTree
+ Assert.Equal(6, sum1)
+ Assert.Equal(6, sum2)
+
+ []
+ let floatAdd () =
+ let sumFunc acc value = acc + value
+ let sum1 = foldLeft sumFunc 0.0f floatTree
+ let sum2 = foldRight sumFunc 0.0f floatTree
+ Assert.Equal(6.00f, sum1, 1)
+ Assert.Equal(6.00f, sum2, 1)
+
+ []
+ let charAdd () =
+ let sumFunc acc value = acc + (int value)
+ let sum1 = foldLeft sumFunc 0 charTree
+ let sum2 = foldRight sumFunc 0 charTree
+ Assert.Equal(294, sum1)
+ Assert.Equal(294, sum2)
+
+
+ []
+ let intMult () =
+ let sumFunc acc value = acc * value
+ let sum1 = foldLeft sumFunc 1 intTree
+ let sum2 = foldRight sumFunc 1 intTree
+ Assert.Equal(6, sum1)
+ Assert.Equal(6, sum2)
+
+ []
+ let floatMult () =
+ let sumFunc acc value = acc * value
+ let sum1 = foldLeft sumFunc 1.0f floatTree
+ let sum2 = foldRight sumFunc 1.0f floatTree
+ Assert.Equal(6.00f, sum1, 1)
+ Assert.Equal(6.00f, sum2, 1)
+
+ []
+ let charMult () =
+ let sumFunc acc value = acc * (int value)
+ let sum1 = foldLeft sumFunc 1 charTree
+ let sum2 = foldRight sumFunc 1 charTree
+ Assert.Equal(941094, sum1)
+ Assert.Equal(941094, sum2)
+
+
+module tHighOfTree =
+ open dataAndFuncs
+
+ []
+ let high () =
+ let oneHigh = high oneLeaf
+ let intHigh = high intTree
+ let floatHigh = high floatTree
+ let charHigh = high charTree
+ let arrayHigh = high arrayTree
+
+ Assert.Equal(1, oneHigh)
+ Assert.Equal(3, intHigh)
+ Assert.Equal(3, floatHigh)
+ Assert.Equal(3, charHigh)
+ Assert.Equal(3, arrayHigh)
diff --git a/src/Library/Functions.fs b/src/Functions/Functions.fs
similarity index 96%
rename from src/Library/Functions.fs
rename to src/Functions/Functions.fs
index 44984563..cde2f069 100644
--- a/src/Library/Functions.fs
+++ b/src/Functions/Functions.fs
@@ -1,43 +1,44 @@
-namespace Functions
-
-
-module Factorial =
- let rec factorial n =
- if n < 0 then
- failwith "The factorial of negative numbers is not calculated by this program\n"
- elif n = 0 || n = 1 then
- 1
- else
- n * factorial (n - 1)
-
-
-module Fibinacci =
-
- type Matrix = int64 array array
-
- let private multiply (m1: Matrix) (m2: Matrix) : Matrix =
- [| [| m1.[0].[0] * m2.[0].[0] + m1.[0].[1] * m2.[1].[0]
- m1.[0].[0] * m2.[0].[1] + m1.[0].[1] * m2.[1].[1] |]
- [| m1.[1].[0] * m2.[0].[0] + m1.[1].[1] * m2.[1].[0]
- m1.[1].[0] * m2.[0].[1] + m1.[1].[1] * m2.[1].[1] |] |]
-
- let rec private power (matrix: Matrix) (n: int) : Matrix =
- if n = 1 then
- matrix
- else
- let halfPower = power matrix (n / 2)
- let result = multiply halfPower halfPower
- if n % 2 = 0 then result else multiply result matrix
-
- let fibonacci (n: int) : int64 =
- if n < 0 then
- failwith "Fibonacci numbers for negative n are not defined\n"
-
- if n = 0 then
- 0L
- elif n = 1 then
- 1L
- else
- let mainMatrix = [| [| 1L; 1L |]; [| 1L; 0L |] |]
- let resultMatrix = power mainMatrix (n - 1)
- resultMatrix.[0].[0]
+namespace Functions
+
+
+module Factorial =
+
+ let rec factorial n =
+ if n < 0 then
+ failwith "The factorial of negative numbers is not calculated by this program\n"
+ elif n = 0 || n = 1 then
+ 1
+ else
+ n * factorial (n - 1)
+
+
+module Fibinacci =
+
+ type Matrix = int64 array array
+
+ let private multiply (m1: Matrix) (m2: Matrix) : Matrix =
+ [| [| m1.[0].[0] * m2.[0].[0] + m1.[0].[1] * m2.[1].[0]
+ m1.[0].[0] * m2.[0].[1] + m1.[0].[1] * m2.[1].[1] |]
+ [| m1.[1].[0] * m2.[0].[0] + m1.[1].[1] * m2.[1].[0]
+ m1.[1].[0] * m2.[0].[1] + m1.[1].[1] * m2.[1].[1] |] |]
+
+ let rec private power (matrix: Matrix) (n: int) : Matrix =
+ if n = 1 then
+ matrix
+ else
+ let halfPower = power matrix (n / 2)
+ let result = multiply halfPower halfPower
+ if n % 2 = 0 then result else multiply result matrix
+
+ let fibonacci (n: int) : int64 =
+ if n < 0 then
+ failwith "Fibonacci numbers for negative n are not defined\n"
+
+ if n = 0 then
+ 0L
+ elif n = 1 then
+ 1L
+ else
+ let mainMatrix = [| [| 1L; 1L |]; [| 1L; 0L |] |]
+ let resultMatrix = power mainMatrix (n - 1)
+ resultMatrix.[0].[0]
diff --git a/src/Functions/Functions.fsproj b/src/Functions/Functions.fsproj
new file mode 100644
index 00000000..56277329
--- /dev/null
+++ b/src/Functions/Functions.fsproj
@@ -0,0 +1,12 @@
+
+
+
+ net8.0
+ true
+
+
+
+
+
+
+
diff --git a/src/Graphs/Graphs.fs b/src/Graphs/Graphs.fs
new file mode 100644
index 00000000..0986c9f3
--- /dev/null
+++ b/src/Graphs/Graphs.fs
@@ -0,0 +1,95 @@
+namespace Graphs
+
+open LineralAlgebra
+open System
+
+
+type Edjes<'t> =
+ | Some of array<'t>
+ | None
+ member this.Min (func: array<'t> -> 't) =
+ match this with
+ | None -> failwith "Edges data type is None"
+ | Some array -> func array
+
+
+module Graphs =
+ let rec private findValue (qtree: QTree<'t>) (size: int) i j =
+ match qtree with
+ | Leaf value -> value
+ | Node(nw, ne, sw, se) ->
+ if i < size / 2 && j < size / 2 then
+ findValue nw (size / 2) i j
+ elif i < size / 2 && j >= size / 2 then
+ findValue ne (size / 2) i (j - size / 2)
+ elif i >= size / 2 && j < size / 2 then
+ findValue sw (size / 2) (i - size / 2) j
+ else
+ findValue se (size / 2) (i - size / 2) (j - size / 2)
+
+ let private toAdjacencyMatrix (graph: Matrix>) =
+ let func (value: Edjes<'t>) =
+ match value with
+ | Some _ -> 1
+ | None -> 0
+ let res = Matrix.map func graph
+ res
+
+ let private opMult x y =
+ if x = 1 && y = 1 then 1
+ else 0
+
+ let private opAdd x y =
+ if x = 0 && y = 0 then 0
+ else 1
+
+
+ /// Finds the shortest path between vertices i and j of the graph.
+ /// A graph in which the shortest path must be found.
+ /// Row coordinate of the adjacency matrix of the graph.
+ /// Column coordinate of the adjacency matrix of a graph.
+ /// Finds mim 't in 't array.
+ /// Shortest path length.
+ let shortestWay (graph: Matrix>) (i: int) (j: int) (func: array<'t> -> 't) =
+ if i < 0 then failwithf "\n\nThe row coordinate i must be > 0\nYour i: %d\n" i
+ elif j < 0 then failwithf "\n\nThe column coordinate j must be > 0\nYour j: %d\n" j
+ elif i >= graph.n then failwithf "\n\nThis row coordinate does not exist\nMaximum column coordinate: %d\nYour coordinate: %d\n" graph.n i
+ elif j >= graph.n then failwithf "\n\nThis column coordinate does not exist\nMaximum row coordinate: %d\nYour coordinate: %d\n" graph.n j
+
+ let handleLeaf edjes =
+ match edjes with
+ | None ->
+ printfn "There is no path from %d to %d" i j
+ Unchecked.defaultof<'t>
+ | Some _ ->
+ edjes.Min func
+
+ let rec findValue (qtree: QTree>) (size: int) i j : 't =
+ match qtree with
+ | Leaf value -> handleLeaf value
+ | Node(nw, ne, sw, se) ->
+ if i < size / 2 && j < size / 2 then
+ findValue nw (size / 2) i j
+ elif i < size / 2 && j >= size / 2 then
+ findValue ne (size / 2) i (j - size / 2)
+ elif i >= size / 2 && j < size / 2 then
+ findValue sw (size / 2) (i - size / 2) j
+ else
+ findValue se (size / 2) (i - size / 2) (j - size / 2)
+
+ let value = findValue graph.qtree graph.n i j
+ value
+
+
+ /// Creates a new graph that is the transitive closure of the underected graph given as argument.
+ /// The graph whose transitive closure is to be constructed.
+ /// Transitive closure graph.
+ let transitiveClosure (graph: Matrix>) =
+ let adjM = toAdjacencyMatrix graph
+ let mutable result = adjM
+
+ for i in 2 .. graph.n do
+ let power = Matrix.multiply result adjM opAdd opMult 0
+ result <- Matrix.map2 opAdd result power
+
+ result
\ No newline at end of file
diff --git a/src/Graphs/Graphs.fsproj b/src/Graphs/Graphs.fsproj
new file mode 100644
index 00000000..5adb60d9
--- /dev/null
+++ b/src/Graphs/Graphs.fsproj
@@ -0,0 +1,16 @@
+
+
+
+ net8.0
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ImageProcessing/ImageProcessing.fs b/src/ImageProcessing/ImageProcessing.fs
new file mode 100644
index 00000000..653a8620
--- /dev/null
+++ b/src/ImageProcessing/ImageProcessing.fs
@@ -0,0 +1,241 @@
+namespace ImageProcessing
+
+open SixLabors.ImageSharp
+open SixLabors.ImageSharp.PixelFormats
+
+[]
+type Image =
+ val Data: array
+ val Width: int
+ val Height: int
+ val Name: string
+
+ new(data, width, height, name) =
+ {
+ Data = data
+ Width = width
+ Height = height
+ Name = name
+ }
+ static member Create(width: int, height: int) =
+ let data = Array.init (height * width) (fun _ -> Rgba32(0uy, 0uy, 0uy, 255uy))
+ Image(data, width, height, "New Image")
+
+
+module ImProcessing =
+
+ let gaussianBlur =
+ [|
+ [| 1; 4; 6; 4; 1 |]
+ [| 4; 16; 24; 16; 4 |]
+ [| 6; 24; 36; 24; 6 |]
+ [| 4; 16; 24; 16; 4 |]
+ [| 1; 4; 6; 4; 1 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / 256.0f))
+
+ let motionDiagonal135deg =
+ [|
+ [| 1; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 1; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 1; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 1; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 1; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 1; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 1; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 1 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / 9.0f))
+
+ let motionDiagonal315deg =
+ [|
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 1 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 1; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 1; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 1; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 1; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 1; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 1; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 1; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / 9.0f))
+
+ let motionVertical =
+ [|
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 1; 0; 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / 9.0f))
+
+ let motionHorizontal =
+ [|
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 1; 1; 1; 1; 1; 1; 1; 1; 1 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0; 0; 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / 9.0f))
+
+ let edgesHorizontal =
+ [|
+ [| 0; 0; -1; 0; 0 |]
+ [| 0; 0; -1; 0; 0 |]
+ [| 0; 0; 2; 0; 0 |]
+ [| 0; 0; 0; 0; 0 |]
+ [| 0; 0; 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let edgesVertical =
+ [|
+ [| 0; 0; -1; 0; 0 |]
+ [| 0; 0; -1; 0; 0 |]
+ [| 0; 0; 4; 0; 0 |]
+ [| 0; 0; -1; 0; 0 |]
+ [| 0; 0; -1; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let edgesDioganal135deg =
+ [|
+ [| -1; 0; 0; 0; 0 |]
+ [| 0; -2; 0; 0; 0 |]
+ [| 0; 0; 6; 0; 0 |]
+ [| 0; 0; 0; -2; 0 |]
+ [| 0; 0; 0; 0; -1 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let edgesDioganal315deg =
+ [|
+ [| 0; 0; 0; 0; -1 |]
+ [| 0; 0; 0; -2; 0 |]
+ [| 0; 0; 6; 0; 0 |]
+ [| 0; -2; 0; -0; 0 |]
+ [| -1; 0; 0; 0; 0 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let edgesAllDirections =
+ [|
+ [| -1; -1; -1 |]
+ [| -1; 8; -1 |]
+ [| -1; -1; -1 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let sharpen =
+ [|
+ [| -1; -1; -1 |]
+ [| -1; 9; -1 |]
+ [| -1; -1; -1 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let sharpenSoft =
+ [|
+ [| -1; -1; -1; -1; -1 |]
+ [| -1; 2; 2; 2; -1 |]
+ [| -1; 2; 8; 2; -1 |]
+ [| -1; 2; 2; 2; -1 |]
+ [| -1; -1; -1; -1; -1 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / 8.0f))
+
+ let sharpenWithEdges =
+ [|
+ [| 1; 1; 1 |]
+ [| 1; -7; 1 |]
+ [| 1; 1; 1 |]
+ |]
+ |> Array.map (Array.map float32)
+
+ let emboss =
+ [|
+ [| -1; -1; 0 |]
+ [| -1; 0; 1 |]
+ [| 0; 1; 1 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / + 128.0f))
+
+ let embossHard =
+ [|
+ [|-1; -1; -1; -1; 0 |]
+ [|-1; -1; -1; 0; 1 |]
+ [|-1; -1; 0; 1; 1 |]
+ [|-1; 0; 1; 1; 1 |]
+ [| 0; 1; 1; 1; 1 |]
+ |]
+ |> Array.map (Array.map (fun x -> (float32 x) / + 128.0f))
+
+
+ let loadAsRgba2D (file: string) =
+ let img = Image.Load file
+ let res = Array2D.zeroCreate img.Height img.Width
+
+ for i in 0 .. img.Width - 1 do
+ for j in 0 .. img.Height - 1 do
+ res.[j, i] <- img.[i, j]
+
+ res
+
+ let saveRgbaImage (rgbaData: Rgba32[,]) file =
+ let h = rgbaData.GetLength(0)
+ let w = rgbaData.GetLength(1)
+
+ use img = new Image(w, h)
+
+ for x in 0 .. h - 1 do
+ for y in 0 .. w - 1 do
+ img.[y, x] <- rgbaData.[x, y]
+
+ img.Save(file)
+
+ let applyFilter (filter: float32[][]) (img: Rgba32[,]) =
+ let imgH = img.GetLength 0
+ let imgW = img.GetLength 1
+
+ let filterD = (Array.length filter) / 2
+ let filter = Array.concat filter
+
+ let processPixel px py =
+ let dataToHandle = [|
+ for i in px - filterD .. px + filterD do
+ for j in py - filterD .. py + filterD do
+ if i < 0 || i >= imgH || j < 0 || j >= imgW then
+ (0.0f, 0.0f, 0.0f)
+ else
+ let pixel = img.[i, j]
+ (float32 pixel.R, float32 pixel.G, float32 pixel.B)
+ |]
+
+ let mutable rSum = 0.0f
+ let mutable gSum = 0.0f
+ let mutable bSum = 0.0f
+
+ Array.iteri (fun index (r, g, b) ->
+ rSum <- rSum + r * filter.[index]
+ gSum <- gSum + g * filter.[index]
+ bSum <- bSum + b * filter.[index]
+ ) dataToHandle
+
+ (byte rSum, byte gSum, byte bSum)
+
+ Array2D.mapi (fun x y _ ->
+ let (r, g, b) = processPixel x y
+ Rgba32(r, g, b, img.[x, y].A)
+ ) img
\ No newline at end of file
diff --git a/src/ImageProcessing/ImageProcessing.fsproj b/src/ImageProcessing/ImageProcessing.fsproj
new file mode 100644
index 00000000..b2e0d7d1
--- /dev/null
+++ b/src/ImageProcessing/ImageProcessing.fsproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net8.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ImageProcessing/Program.fs b/src/ImageProcessing/Program.fs
new file mode 100644
index 00000000..f78667ad
--- /dev/null
+++ b/src/ImageProcessing/Program.fs
@@ -0,0 +1,72 @@
+open ImageProcessing.ImProcessing
+open Argu
+
+
+type Filters =
+ | gaussianBlur = 1
+ | motionDiagonal135deg = 2
+ | motionDiagonal315deg = 3
+ | motionVertical = 4
+ | motionHorizontal = 5
+ | edgesHorizontal = 6
+ | edgesVertical = 7
+ | edgesDioganal135deg = 8
+ | edgesDioganal315deg = 9
+ | edgesAllDirections = 10
+ | sharpen = 11
+ | sharpenSoft = 12
+ | sharpenWithEdges = 13
+ | emboss = 14
+ | embossHard = 15
+
+type Arguments =
+ | [] Input_File of string
+ | [] Out_File of string
+ | [] Filters of list
+ interface IArgParserTemplate with
+ member this.Usage =
+ match this with
+ | Input_File _ -> "File to process."
+ | Out_File _ -> "Where to save result."
+ | Filters _ -> "Which filters to apply (comma-separated)."
+
+
+[]
+let main argv =
+
+ let parser = ArgumentParser.Create(programName = "ImageProcessing")
+ let results = parser.Parse argv
+
+ let inFile = results.GetResult Input_File
+ let outFile = results.GetResult Out_File
+ let filters = results.GetResult Filters
+
+ let inImage = loadAsRgba2D inFile
+
+ let resultImage =
+ filters |> List.fold (fun img filter ->
+ match filter with
+ | Filters.gaussianBlur -> applyFilter gaussianBlur img
+ | Filters.motionDiagonal135deg -> applyFilter motionDiagonal135deg img
+ | Filters.motionDiagonal315deg -> applyFilter motionDiagonal315deg img
+ | Filters.motionVertical -> applyFilter motionVertical img
+ | Filters.motionHorizontal -> applyFilter motionHorizontal img
+ | Filters.edgesHorizontal -> applyFilter edgesHorizontal img
+ | Filters.edgesVertical -> applyFilter edgesVertical img
+ | Filters.edgesDioganal135deg -> applyFilter edgesDioganal135deg img
+ | Filters.edgesDioganal315deg -> applyFilter edgesDioganal315deg img
+ | Filters.edgesAllDirections -> applyFilter edgesAllDirections img
+ | Filters.sharpen -> applyFilter sharpen img
+ | Filters.sharpenSoft -> applyFilter sharpenSoft img
+ | Filters.sharpenWithEdges -> applyFilter sharpenWithEdges img
+ | Filters.emboss -> applyFilter emboss img
+ | Filters.embossHard -> applyFilter embossHard img
+ | _ ->
+ printfn "Unknown filter"
+ img
+
+ ) inImage
+
+ saveRgbaImage resultImage outFile
+
+ 0
\ No newline at end of file
diff --git a/src/LineralAlgebra/LineralAlgebra.fs b/src/LineralAlgebra/LineralAlgebra.fs
new file mode 100644
index 00000000..0bc901a1
--- /dev/null
+++ b/src/LineralAlgebra/LineralAlgebra.fs
@@ -0,0 +1,265 @@
+namespace LineralAlgebra
+
+
+type QTree<'t> =
+ | Leaf of 't
+ | Node of QTree<'t> * QTree<'t> * QTree<'t> * QTree<'t>
+
+
+type Matrix<'t> =
+ {
+ n: int;
+ qtree: QTree<'t>
+ }
+
+
+module private Private =
+
+ let rec toCorrectQTree qtree =
+ match qtree with
+ | Leaf value -> Leaf value
+
+ | Node (nw, ne, se, sw) ->
+ let NW = toCorrectQTree nw
+ let NE = toCorrectQTree ne
+ let SE = toCorrectQTree se
+ let SW = toCorrectQTree sw
+
+ match NW, NE, SE, SW with
+ | Leaf value1,
+ Leaf value2,
+ Leaf value3,
+ Leaf value4
+ when value1 = value2 && value2 = value3 && value3 = value4 ->
+
+ Leaf value1
+
+ | _ -> Node (NW, NE, SE, SW)
+
+
+open Private
+
+
+module QTrees =
+ /// The function goes through the whole tree and merges (if any) 4 leaves with the same values, coming from one node into one leaf of the original node with the original value.
+ /// The input qtree.
+ /// Correctly built qtree.
+ let toCorrectQTree qtree =
+ qtree |> toCorrectQTree
+
+ /// Builds a new qtree whose elements are the results of applying the given function to each of the elements of the qtree.
+ /// The function to transform elements of the qtree.
+ /// The input qtree.
+ /// The qtree of transformed elements.
+ let rec map mapping qtree =
+ match qtree with
+ | Leaf value -> Leaf (mapping value)
+ | Node (nw,ne, se, sw) ->
+ Node (map mapping nw, map mapping ne, map mapping se, map mapping sw)
+ |> toCorrectQTree
+
+ /// Builds a new qtree whose elements are the results of applying the given function to the corresponding elements of the two collections pairwise.
+ /// The function to transform the pairs of the input elements.
+ /// The first input qtree.
+ /// The second input qtree.
+ /// The qtree of transformed elements.
+ let rec map2 mapping qtree1 qtree2 =
+ match qtree1, qtree2 with
+ | Leaf value1, Leaf value2 ->
+ Leaf (mapping value1 value2)
+
+ | Leaf value, Node (nw, ne, se, sw) ->
+ Node (
+ map2 mapping (Leaf value) nw,
+ map2 mapping (Leaf value) ne,
+ map2 mapping (Leaf value) se,
+ map2 mapping (Leaf value) sw
+ )
+
+ | Node (nw, ne, se, sw), Leaf value ->
+ Node (
+ map2 mapping nw (Leaf value),
+ map2 mapping ne (Leaf value),
+ map2 mapping se (Leaf value),
+ map2 mapping sw (Leaf value)
+ )
+
+ | Node (nw, ne, se, sw), Node (NW, NE, SE, SW) ->
+ Node (
+ map2 mapping nw NW,
+ map2 mapping ne NE,
+ map2 mapping se SE,
+ map2 mapping sw SW
+ )
+ |> toCorrectQTree
+
+ /// Creates a square array2D with elements from a qtree.
+ /// The qtree from which the elements are taken.
+ /// The output array size can only be a power of two due to the structure of qtrees.
+ /// The created array2D.
+ let qtreeToArray2D (qtree: QTree<'t>) (size: int) : 't[,] =
+ if size <= 0 || size &&& (size - 1) <> 0 then
+ failwithf "\n\n The size is not a power of two or <= 0\n\n size: %d\n" size
+
+ let rec qtrToArray2D (qtree: QTree<'t>) (size: int) : 't[,] =
+ match qtree with
+ | Leaf value when size = 1 ->
+ Array2D.create 1 1 value
+
+ | Leaf value when size > 1 ->
+ Array2D.create size size value
+
+ | Node (nw, ne, sw, se) ->
+ let NW = qtrToArray2D nw (size / 2)
+ let NE = qtrToArray2D ne (size / 2)
+ let SW = qtrToArray2D sw (size / 2)
+ let SE = qtrToArray2D se (size / 2)
+
+ let mainSize = Array2D.length1 NW
+
+ let matrix = Array2D.create (mainSize * 2) (mainSize * 2) Unchecked.defaultof<'t>
+
+ for i in 0 .. mainSize - 1 do
+ for j in 0 .. mainSize - 1 do
+ matrix[i, j] <- NW[i, j]
+ matrix[i, j + mainSize] <- NE[i, j]
+ matrix[i + mainSize, j] <- SW[i, j]
+ matrix[i + mainSize, j + mainSize] <- SE[i, j]
+
+ matrix
+
+ | Leaf _ -> failwith "Not Implemented"
+
+ qtrToArray2D qtree size
+
+ /// Calculates the number of levels at which tree nodes are located, from the root to any leaf.
+ /// The input qtree.
+ /// The number of levels in the qtree.
+ let rec height qtree =
+ match qtree with
+ | Leaf _-> 1
+ | Node (nw, ne, se, sw) ->
+ let heights = [| height nw; height ne; height se; height sw |]
+ Array.max heights + 1
+
+
+module Matrix =
+
+ /// Builds a new matrix whose elements are the results of applying the given function to each of the elements of the matrix.
+ /// The function to transform elements of the matrix.
+ /// The input matrix.
+ /// The matrix of transformed elements.
+ let map mapping (matr: Matrix<'t>) =
+ let res = QTrees.map mapping matr.qtree
+ { n = matr.n; qtree = res }
+
+ /// Builds a new matrix whose elements are the results of applying the given function to the corresponding elements of the two collections pairwise.
+ /// The function to transform the pairs of the input elements.
+ /// The first input matrix.
+ /// The second input matrix.
+ /// The matrix of transformed elements.
+ let map2 mapping (matr1: Matrix<'t>) (matr2: Matrix<'t>) =
+ let res = QTrees.map2 mapping matr1.qtree matr2.qtree
+ { n = max matr1.n matr2.n; qtree = res }
+
+ let rec private add qtree1 qtree2 size (opAdd: 't -> 't -> 't) (opMult: 't -> 't -> 't) =
+ match qtree1, qtree2 with
+ | Leaf value1, Leaf value2 ->
+ Leaf(opAdd value1 value2)
+
+ | Leaf _ , Node(nw, ne, sw, se) ->
+ Node(
+ add qtree1 nw (size / 2) opAdd opMult,
+ add qtree1 ne (size / 2) opAdd opMult,
+ add qtree1 sw (size / 2) opAdd opMult,
+ add qtree1 se (size / 2) opAdd opMult
+ )
+
+ | Node(nw, ne, sw, se), Leaf _ ->
+ Node(
+ add nw qtree2 (size / 2) opAdd opMult,
+ add ne qtree2 (size / 2) opAdd opMult,
+ add sw qtree2 (size / 2) opAdd opMult,
+ add se qtree2 (size / 2) opAdd opMult
+ )
+
+ | Node(nw, ne, sw, se), Node(NW, NE, SW, SE) ->
+ Node(
+ add nw NW (size / 2) opAdd opMult,
+ add ne NE (size / 2) opAdd opMult,
+ add sw SW (size / 2) opAdd opMult,
+ add se SE (size / 2) opAdd opMult
+ )
+
+ let rec private mult qtree1 qtree2 size (opAdd: 't -> 't -> 't) (opMult: 't -> 't -> 't) (neutral: 't) =
+ match qtree1, qtree2 with
+ | Leaf value1, Leaf value2 ->
+ let add = opMult value1 value2
+ let mutable value = neutral
+
+ for i in 0 .. size - 1 do
+ value <- opAdd value add
+
+ Leaf value
+
+ | Leaf _ , Node(nw, ne, sw, se) ->
+ let Vnw = mult qtree1 nw (size / 2) opAdd opMult neutral
+ let Vsw = mult qtree1 sw (size / 2) opAdd opMult neutral
+ let Vne = mult qtree1 ne (size / 2) opAdd opMult neutral
+ let Vse = mult qtree1 se (size / 2) opAdd opMult neutral
+
+ Node(
+ add Vnw Vsw (size / 2) opAdd opMult,
+ add Vne Vse (size / 2) opAdd opMult,
+ add Vnw Vsw (size / 2) opAdd opMult,
+ add Vne Vse (size / 2) opAdd opMult
+ )
+
+ | Node(nw, ne, sw, se), Leaf _ ->
+ let nwV = mult nw qtree2 (size / 2) opAdd opMult neutral
+ let neV = mult ne qtree2 (size / 2) opAdd opMult neutral
+ let swV = mult sw qtree2 (size / 2) opAdd opMult neutral
+ let seV = mult se qtree2 (size / 2) opAdd opMult neutral
+
+ Node(
+ add nwV neV (size / 2) opAdd opMult,
+ add nwV neV (size / 2) opAdd opMult,
+ add swV seV (size / 2) opAdd opMult,
+ add swV seV (size / 2) opAdd opMult
+ )
+
+ | Node(nw, ne, sw, se), Node(NW, NE, SW, SE) ->
+ let nwNW = mult nw NW (size / 2) opAdd opMult neutral
+ let neSW = mult ne SW (size / 2) opAdd opMult neutral
+ let nwNE = mult nw NE (size / 2) opAdd opMult neutral
+ let neSE = mult ne SE (size / 2) opAdd opMult neutral
+ let swNW = mult sw NW (size / 2) opAdd opMult neutral
+ let seSW = mult se SW (size / 2) opAdd opMult neutral
+ let swNE = mult sw NE (size / 2) opAdd opMult neutral
+ let seSE = mult se SE (size / 2) opAdd opMult neutral
+
+ Node(
+ add nwNW neSW (size / 2) opAdd opMult,
+ add nwNE neSE (size / 2) opAdd opMult,
+ add swNW seSW (size / 2) opAdd opMult,
+ add swNE seSE (size / 2) opAdd opMult
+ )
+
+ /// The function assumes that the matrices have already been converted to the same correct size: nxn where n = 2^N.
+ /// First matrix in matrix product.
+ /// Second matrix in matrix product.
+ /// Operation of addition of elements 't.
+ /// Operation of multiplication of elements 't.
+ /// Neutral element by addition.
+ /// Product of matr1 * matr2.
+ let multiply (matr1: Matrix<'t>) (matr2: Matrix<'t>) (opAdd: 't -> 't -> 't) (opMult: 't -> 't -> 't) (neutral: 't) =
+ if matr1.n <> matr2.n then
+ failwithf "\n\n Matr1 and matr2 have different sizes:\n\n Matr1: %d\n Matr2: %d\n" matr1.n matr2.n
+ elif matr1.n <= 0 || matr1.n &&& (matr1.n - 1) <> 0 then
+ failwithf "\n\n The size of matr1 is not a power of two or <= 0\n\n Matr1: %d\n" matr1.n
+ elif matr2.n <= 0 || matr2.n &&& (matr2.n - 1) <> 0 then
+ failwithf "\n\n The size of matr2 is not a power of two or <= 0\n\n Matr1: %d\n" matr2.n
+
+ let result = mult matr1.qtree matr2.qtree matr1.n opAdd opMult neutral
+ let matrix = result |> toCorrectQTree
+ { n = max matr1.n matr2.n; qtree = matrix }
\ No newline at end of file
diff --git a/src/LineralAlgebra/LineralAlgebra.fsproj b/src/LineralAlgebra/LineralAlgebra.fsproj
new file mode 100644
index 00000000..df23649b
--- /dev/null
+++ b/src/LineralAlgebra/LineralAlgebra.fsproj
@@ -0,0 +1,20 @@
+
+
+
+ net8.0
+ true
+ LineralAlgebra
+ 1.2.0
+ Me
+ Also me
+ This package is part of my homework that will be used in my other homework. But if you somehow stumbled upon it, here's its readme
+
+ MIT
+ I'm fixing all sorts of little things regarding documentation
+
+
+
+
+
+
+
diff --git a/src/Library/ArraySorts.fs b/src/Sortings/ArraySorts.fs
similarity index 100%
rename from src/Library/ArraySorts.fs
rename to src/Sortings/ArraySorts.fs
diff --git a/src/Library/MyListSorts.fs b/src/Sortings/MyListSorts.fs
similarity index 100%
rename from src/Library/MyListSorts.fs
rename to src/Sortings/MyListSorts.fs
diff --git a/src/Library/Library.fsproj b/src/Sortings/Sortings.fsproj
similarity index 85%
rename from src/Library/Library.fsproj
rename to src/Sortings/Sortings.fsproj
index 240b2e4a..da92f555 100644
--- a/src/Library/Library.fsproj
+++ b/src/Sortings/Sortings.fsproj
@@ -6,7 +6,6 @@
-
diff --git a/src/Trees/Trees.fs b/src/Trees/Trees.fs
new file mode 100644
index 00000000..43914c1b
--- /dev/null
+++ b/src/Trees/Trees.fs
@@ -0,0 +1,66 @@
+namespace Trees
+
+type NonEmptyList<'t> =
+ | Single of 't
+ | Cons of 't * NonEmptyList<'t>
+
+type Tree<'t> =
+ | Node of Tree<'t> NonEmptyList
+ | Leaf of 't
+
+
+module NonEmptyList =
+
+ let rec map func list =
+ match list with
+ | Single value -> Single (func value)
+ | Cons(head, tail) -> Cons(func head, map func tail)
+
+ let rec fold func acc list =
+ match list with
+ | Single value -> func value acc
+ | Cons(head, tail) ->
+ let newAcc = func head acc
+ fold func newAcc tail
+
+ let rec foldBack func list acc =
+ match list with
+ | Single value -> func value acc
+ | Cons(head, tail) -> foldBack func tail (func head acc)
+
+ let rec max list =
+ match list with
+ | Single x -> x
+ | Cons (head, tail) ->
+ let tailMax = max tail
+ if head > tailMax then head else tailMax
+
+
+module Tree =
+
+ let rec map func tree =
+ match tree with
+ | Leaf value -> Leaf (func value)
+ | Node children ->
+ Node (NonEmptyList.map (map func) children)
+
+ let rec foldLeft func acc tree =
+ match tree with
+ | Leaf value -> func acc value
+ | Node children ->
+ NonEmptyList.fold (fun child acc -> foldLeft func acc child) acc children
+
+ let rec foldRight func acc tree =
+ match tree with
+ | Leaf value -> func acc value
+ | Node children ->
+ NonEmptyList.foldBack (fun child acc -> foldRight func acc child) children acc
+
+ let rec high tree=
+ match tree with
+ | Leaf _ -> 1
+ | Node children ->
+ let heights = NonEmptyList.map high children
+ 1 + NonEmptyList.max heights
+
+
\ No newline at end of file
diff --git a/src/Trees/Trees.fsproj b/src/Trees/Trees.fsproj
new file mode 100644
index 00000000..241cc98c
--- /dev/null
+++ b/src/Trees/Trees.fsproj
@@ -0,0 +1,12 @@
+
+
+
+ net8.0
+ true
+
+
+
+
+
+
+