diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/.editorconfig b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/.editorconfig
new file mode 100644
index 0000000..51a0b79
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/.editorconfig
@@ -0,0 +1,125 @@
+[*.cs]
+
+# SA1600: Elements should be documented
+dotnet_diagnostic.SA1600.severity = none
+
+[*.cs]
+#### Стили именования ####
+
+# Правила именования
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Спецификации символов
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Стили именования
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+csharp_style_throw_expression = true:suggestion
+csharp_style_prefer_null_check_over_type_check = true:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_indent_labels = one_less_than_current
+
+[*.vb]
+#### Стили именования ####
+
+# Правила именования
+
+dotnet_naming_rule.interface_should_be_начинается_с_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_начинается_с_i.symbols = interface
+dotnet_naming_rule.interface_should_be_начинается_с_i.style = начинается_с_i
+
+dotnet_naming_rule.типы_should_be_всечастиспрописнойбуквы.severity = suggestion
+dotnet_naming_rule.типы_should_be_всечастиспрописнойбуквы.symbols = типы
+dotnet_naming_rule.типы_should_be_всечастиспрописнойбуквы.style = всечастиспрописнойбуквы
+
+dotnet_naming_rule.не_являющиеся_полем_члены_should_be_всечастиспрописнойбуквы.severity = suggestion
+dotnet_naming_rule.не_являющиеся_полем_члены_should_be_всечастиспрописнойбуквы.symbols = не_являющиеся_полем_члены
+dotnet_naming_rule.не_являющиеся_полем_члены_should_be_всечастиспрописнойбуквы.style = всечастиспрописнойбуквы
+
+# Спецификации символов
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.типы.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.типы.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
+dotnet_naming_symbols.типы.required_modifiers =
+
+dotnet_naming_symbols.не_являющиеся_полем_члены.applicable_kinds = property, event, method
+dotnet_naming_symbols.не_являющиеся_полем_члены.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
+dotnet_naming_symbols.не_являющиеся_полем_члены.required_modifiers =
+
+# Стили именования
+
+dotnet_naming_style.начинается_с_i.required_prefix = I
+dotnet_naming_style.начинается_с_i.required_suffix =
+dotnet_naming_style.начинается_с_i.word_separator =
+dotnet_naming_style.начинается_с_i.capitalization = pascal_case
+
+dotnet_naming_style.всечастиспрописнойбуквы.required_prefix =
+dotnet_naming_style.всечастиспрописнойбуквы.required_suffix =
+dotnet_naming_style.всечастиспрописнойбуквы.word_separator =
+dotnet_naming_style.всечастиспрописнойбуквы.capitalization = pascal_case
+
+dotnet_naming_style.всечастиспрописнойбуквы.required_prefix =
+dotnet_naming_style.всечастиспрописнойбуквы.required_suffix =
+dotnet_naming_style.всечастиспрописнойбуквы.word_separator =
+dotnet_naming_style.всечастиспрописнойбуквы.capitalization = pascal_case
+
+[*.{cs,vb}]
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/ParallelMatrixMultiplication.Test.csproj b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/ParallelMatrixMultiplication.Test.csproj
new file mode 100644
index 0000000..944a8ea
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/ParallelMatrixMultiplication.Test.csproj
@@ -0,0 +1,52 @@
+
+
+
+ net9.0
+ latest
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestLoadFromFile.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestLoadFromFile.cs
new file mode 100644
index 0000000..bcc7691
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestLoadFromFile.cs
@@ -0,0 +1,54 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication.Test;
+
+public class TestLoadFromFile
+{
+ private Matrix firstExpectedMatrix;
+ private Matrix secondExpectedMatrix;
+
+ [SetUp]
+ public void Setup()
+ {
+ this.firstExpectedMatrix = new Matrix(new int[,]
+ {
+ { 15, 16, 17 },
+ { 20, 23, 26 },
+ { 29, 32, 35 },
+ });
+
+ this.secondExpectedMatrix = new Matrix(new int[,]
+ {
+ { 1, 2, 3, 4, 5 },
+ { 6, 7, 8, 9, 10 },
+ });
+ }
+
+ [Test]
+ public void LoadFromFile_SquareMatrix_ShouldReturnExpectedResult()
+ {
+ var result = Matrix.LoadFromFile("firstTestFileForRead.txt");
+ for (int i = 0; i < result.Rows; ++i)
+ {
+ for (int j = 0; j < result.Columns; ++j)
+ {
+ Assert.That(result[i, j], Is.EqualTo(this.firstExpectedMatrix[i, j]));
+ }
+ }
+ }
+
+ [Test]
+ public void LoadFromFile_NotSquareMatrix_ShouldReturnExpectedResult()
+ {
+ var result = Matrix.LoadFromFile("secondTestFileForRead.txt");
+ for (int i = 0; i < result.Rows; ++i)
+ {
+ for (int j = 0; j < result.Columns; ++j)
+ {
+ Assert.That(result[i, j], Is.EqualTo(this.secondExpectedMatrix[i, j]));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestSaveToFile.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestSaveToFile.cs
new file mode 100644
index 0000000..1e4cd5a
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestSaveToFile.cs
@@ -0,0 +1,46 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication.Test;
+
+public class TestSaveToFile
+{
+ private Matrix matrixToSave;
+ private string currentFilePath;
+
+ [SetUp]
+ public void Setup()
+ {
+ this.matrixToSave = new Matrix(new int[,]
+ {
+ { 99, 90, 88, 80 },
+ { 77, 70, 66, 60 },
+ { 55, 50, 44, 40 },
+ });
+
+ this.currentFilePath = "Test_STF.txt";
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ if (File.Exists(this.currentFilePath))
+ {
+ File.Delete(this.currentFilePath);
+ }
+ }
+
+ [Test]
+ public void SaveToFile_ValidData_ShouldCreateExpectedFile()
+ {
+ this.matrixToSave.SaveToFile(this.currentFilePath);
+
+ Assert.That(File.Exists(this.currentFilePath), Is.True);
+
+ string expectedData = File.ReadAllText("expectedForSaveToFileTest.txt");
+ string currentData = File.ReadAllText(this.currentFilePath);
+
+ Assert.That(currentData, Is.EqualTo(expectedData));
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsBothMethodsAreSimilar.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsBothMethodsAreSimilar.cs
new file mode 100644
index 0000000..0218d7a
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsBothMethodsAreSimilar.cs
@@ -0,0 +1,32 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication.Test;
+
+public class TestsBothMethodsAreSimilar
+{
+ private Matrix testRandomMatrixA;
+ private Matrix testRandomMatrixB;
+
+ [SetUp]
+ public void Setup()
+ {
+ this.testRandomMatrixA = Matrix.GenerateRandomMatrix(77, 33);
+ this.testRandomMatrixB = Matrix.GenerateRandomMatrix(33, 77);
+ }
+
+ [Test]
+ public void SequentialAndParallelMultiplication_RandomMatrix_ShouldReturnSameResult()
+ {
+ var parallelResult = MatrixMultiplier.ParallelMultiplication(this.testRandomMatrixA, this.testRandomMatrixB, 4);
+ var sequentialResult = MatrixMultiplier.SequentialMultiplication(this.testRandomMatrixA, this.testRandomMatrixB);
+ for (int i = 0; i < parallelResult.Rows; ++i)
+ {
+ for (int j = 0; j < parallelResult.Columns; ++j)
+ {
+ Assert.That(parallelResult[i, j], Is.EqualTo(sequentialResult[i, j]));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsParallelMultiply.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsParallelMultiply.cs
new file mode 100644
index 0000000..467136c
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsParallelMultiply.cs
@@ -0,0 +1,84 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication.Test;
+
+public class TestsParallelMultiply
+{
+ private Matrix testMatrixA2x2;
+ private Matrix testMatrixB2x2;
+
+ private Matrix testMatrixA2x3;
+ private Matrix testMatrixB3x2;
+
+ private Matrix firstExpectedResult;
+ private Matrix secondExpectedResult;
+
+ [SetUp]
+ public void Setup()
+ {
+ this.testMatrixA2x2 = new Matrix(new int[,]
+ {
+ { 9, 4 },
+ { 5, 1 },
+ });
+
+ this.testMatrixB2x2 = new Matrix(new int[,]
+ {
+ { 5, 3 },
+ { 8, 7 },
+ });
+
+ this.testMatrixA2x3 = new Matrix(new int[,]
+ {
+ { 2, 1, 0 },
+ { 7, -5, 6 },
+ });
+
+ this.testMatrixB3x2 = new Matrix(new int[,]
+ {
+ { -2, 6 },
+ { 4, 2 },
+ { 3, 8 },
+ });
+
+ this.firstExpectedResult = new Matrix(new int[,]
+ {
+ { 77, 55 },
+ { 33, 22 },
+ });
+
+ this.secondExpectedResult = new Matrix(new int[,]
+ {
+ { 0, 14 },
+ { -16, 80 },
+ });
+ }
+
+ [Test]
+ public void ParallelMultiplication_SquareMatrices_ShouldReturnExpectedResult()
+ {
+ var result = MatrixMultiplier.ParallelMultiplication(this.testMatrixA2x2, this.testMatrixB2x2, Environment.ProcessorCount);
+ for (int i = 0; i < result.Rows; ++i)
+ {
+ for (int j = 0; j < result.Columns; ++j)
+ {
+ Assert.That(result[i, j], Is.EqualTo(this.firstExpectedResult[i, j]));
+ }
+ }
+ }
+
+ [Test]
+ public void ParallelMultiplication_NotSquareMatrices_ShouldReturnExpectedResult()
+ {
+ var result = MatrixMultiplier.ParallelMultiplication(this.testMatrixA2x3, this.testMatrixB3x2, Environment.ProcessorCount);
+ for (int i = 0; i < result.Rows; ++i)
+ {
+ for (int j = 0; j < result.Columns; ++j)
+ {
+ Assert.That(result[i, j], Is.EqualTo(this.secondExpectedResult[i, j]));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsSequentialMultiply.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsSequentialMultiply.cs
new file mode 100644
index 0000000..1cbf703
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/TestsSequentialMultiply.cs
@@ -0,0 +1,84 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication.Test;
+
+public class TestsSequentialMultiply
+{
+ private Matrix testMatrixA2x2;
+ private Matrix testMatrixB2x2;
+
+ private Matrix testMatrixA2x3;
+ private Matrix testMatrixB3x2;
+
+ private Matrix firstExpectedResult;
+ private Matrix secondExpectedResult;
+
+ [SetUp]
+ public void Setup()
+ {
+ this.testMatrixA2x2 = new Matrix(new int[,]
+ {
+ { 1, 2 },
+ { 3, 4 },
+ });
+
+ this.testMatrixB2x2 = new Matrix(new int[,]
+ {
+ { 9, 8 },
+ { 7, 6 },
+ });
+
+ this.testMatrixA2x3 = new Matrix(new int[,]
+ {
+ { 2, -3, 1 },
+ { 5, 4, -2 },
+ });
+
+ this.testMatrixB3x2 = new Matrix(new int[,]
+ {
+ { -7, 5 },
+ { 2, -1 },
+ { 4, 3 },
+ });
+
+ this.firstExpectedResult = new Matrix(new int[,]
+ {
+ { 23, 20 },
+ { 55, 48 },
+ });
+
+ this.secondExpectedResult = new Matrix(new int[,]
+ {
+ { -16, 16 },
+ { -35, 15 },
+ });
+ }
+
+ [Test]
+ public void SequentialMultiplication_SquareMatrices_ShouldReturnExpectedResult()
+ {
+ var result = MatrixMultiplier.SequentialMultiplication(this.testMatrixA2x2, this.testMatrixB2x2);
+ for (int i = 0; i < result.Rows; ++i)
+ {
+ for (int j = 0; j < result.Columns; ++j)
+ {
+ Assert.That(result[i, j], Is.EqualTo(this.firstExpectedResult[i, j]));
+ }
+ }
+ }
+
+ [Test]
+ public void SequentialMultiplication_NotSquareMatrices_ShouldReturnExpectedResult()
+ {
+ var result = MatrixMultiplier.SequentialMultiplication(this.testMatrixA2x3, this.testMatrixB3x2);
+ for (int i = 0; i < result.Rows; ++i)
+ {
+ for (int j = 0; j < result.Columns; ++j)
+ {
+ Assert.That(result[i, j], Is.EqualTo(this.secondExpectedResult[i, j]));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/expectedForSaveToFileTest.txt b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/expectedForSaveToFileTest.txt
new file mode 100644
index 0000000..8a1b8b5
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/expectedForSaveToFileTest.txt
@@ -0,0 +1,3 @@
+99 90 88 80
+77 70 66 60
+55 50 44 40
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/firstTestFileForRead.txt b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/firstTestFileForRead.txt
new file mode 100644
index 0000000..dfd68d9
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/firstTestFileForRead.txt
@@ -0,0 +1,3 @@
+15 16 17
+20 23 26
+29 32 35
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/secondTestFileForRead.txt b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/secondTestFileForRead.txt
new file mode 100644
index 0000000..ef25eaa
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/secondTestFileForRead.txt
@@ -0,0 +1,2 @@
+1 2 3 4 5
+6 7 8 9 10
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/stylecop.json b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/stylecop.json
new file mode 100644
index 0000000..ce12f73
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.Test/stylecop.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "documentationRules": {
+ "companyName": "Kalinin Andrew",
+ "copyrightText": "Copyright (c) {companyName}. All rights reserved."
+ }
+ }
+}
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication.sln b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.sln
new file mode 100644
index 0000000..aec2fc3
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.13.35806.99
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParallelMatrixMultiplication", "ParallelMatrixMultiplication\ParallelMatrixMultiplication.csproj", "{96DCD91F-9CF3-4519-8929-C0C38523DBB7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParallelMatrixMultiplication.Test", "ParallelMatrixMultiplication.Test\ParallelMatrixMultiplication.Test.csproj", "{217B9ADC-8DBB-4227-BE0F-6DF9674FF67A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {96DCD91F-9CF3-4519-8929-C0C38523DBB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {96DCD91F-9CF3-4519-8929-C0C38523DBB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {96DCD91F-9CF3-4519-8929-C0C38523DBB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {96DCD91F-9CF3-4519-8929-C0C38523DBB7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {217B9ADC-8DBB-4227-BE0F-6DF9674FF67A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {217B9ADC-8DBB-4227-BE0F-6DF9674FF67A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {217B9ADC-8DBB-4227-BE0F-6DF9674FF67A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {217B9ADC-8DBB-4227-BE0F-6DF9674FF67A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {902A2F58-AB9C-49FA-AD02-157B0D718B30}
+ EndGlobalSection
+EndGlobal
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/ArgumentParser.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/ArgumentParser.cs
new file mode 100644
index 0000000..a321136
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/ArgumentParser.cs
@@ -0,0 +1,28 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication;
+
+///
+/// A class for working with command line arguments.
+///
+public static class ArgumentParser
+{
+ ///
+ /// Analyzes the command line arguments and determines the execution mode.
+ ///
+ /// An array of command line arguments.
+ /// A tuple containing the execution mode and an array of parameters.
+ public static (string Mode, string[] Parametrs) Parse(string[] args)
+ {
+ if (args == null || args.Length == 0)
+ {
+ throw new ArgumentException("Укажите режим работы ('load' или 'matrixTest')");
+ }
+
+ string mode = args[0].ToLower();
+ string[] parametrs = args.Skip(1).ToArray();
+ return (mode, parametrs);
+ }
+}
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/Matrix.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/Matrix.cs
new file mode 100644
index 0000000..bf31fa7
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/Matrix.cs
@@ -0,0 +1,153 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication;
+
+///
+/// A class representing a matrix and operations for working with it.
+///
+public class Matrix
+{
+ ///
+ /// An array for storing matrix elements.
+ ///
+ private readonly int[,] numbers;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The number of specified rows.
+ /// The number of specified columns.
+ public Matrix(int rows, int columns)
+ {
+ this.numbers = new int[rows, columns];
+ this.Rows = rows;
+ this.Columns = columns;
+ }
+
+ ///
+ /// Initializes a new instance of the class from a 2D array.
+ ///
+ /// The 2D array containing matrix values.
+ public Matrix(int[,] data)
+ {
+ this.Rows = data.GetLength(0);
+ this.Columns = data.GetLength(1);
+ this.numbers = (int[,])data.Clone();
+ }
+
+ ///
+ /// Gets number of rows in the matrix.
+ ///
+ public int Rows { get; private set; }
+
+ ///
+ /// Gets number of columns in the matrix.
+ ///
+ public int Columns { get; private set; }
+
+ ///
+ /// Indexer for accessing matrix elements.
+ ///
+ /// Row index.
+ /// Column index.
+ /// The value of the element.
+ public int this[int rows, int columns]
+ {
+ get => this.numbers[rows, columns];
+ }
+
+ ///
+ /// A method for generating a matrix with random values.
+ ///
+ /// Number of lines.
+ /// Number of columns.
+ /// Matrix with random values.
+ public static Matrix GenerateRandomMatrix(int rows, int columns)
+ {
+ Random random = new Random();
+ int[,] data = new int[rows, columns];
+ for (int i = 0; i < rows; i++)
+ {
+ for (int j = 0; j < columns; ++j)
+ {
+ data[i, j] = random.Next(1, 74);
+ }
+ }
+
+ return new Matrix(data);
+ }
+
+ ///
+ /// A method for loading a matrix from a file.
+ ///
+ /// The path to the matrix file.
+ /// The matrix from the file.
+ /// It is thrown if the file is not found.
+ /// It is thrown if the file is empty or contains incorrect data.
+ /// It is thrown if the numbers in the file have an incorrect format.
+ public static Matrix LoadFromFile(string filePath)
+ {
+ if (!File.Exists(filePath))
+ {
+ throw new FileNotFoundException($"Файл {filePath} не найден");
+ }
+
+ string[] lines = File.ReadAllLines(filePath);
+
+ if (lines.Length == 0)
+ {
+ throw new InvalidDataException("Файл пуст");
+ }
+
+ int rows = lines.Length;
+
+ string[] firstRowValues = lines[0].Split(' ', StringSplitOptions.RemoveEmptyEntries);
+ int columnsSize = firstRowValues.Length;
+
+ int[,] data = new int[rows, columnsSize];
+ for (int i = 0; i < rows; ++i)
+ {
+ string[] values = lines[i].Split(' ', StringSplitOptions.RemoveEmptyEntries);
+
+ if (values.Length != columnsSize)
+ {
+ throw new InvalidDataException("Строка имеет некорректное значение стобцов");
+ }
+
+ for (int j = 0; j < columnsSize; ++j)
+ {
+ if (!int.TryParse(values[j], out int parsedValue))
+ {
+ throw new FormatException("Неверный формат числа в строке");
+ }
+
+ data[i, j] = parsedValue;
+ }
+ }
+
+ return new Matrix(data);
+ }
+
+ ///
+ /// A method for saving a matrix to a file.
+ ///
+ /// The path to save the file.
+ public void SaveToFile(string filePath)
+ {
+ using StreamWriter writer = new StreamWriter(filePath);
+ for (int i = 0; i < this.Rows; i++)
+ {
+ for (int j = 0; j < this.Columns; j++)
+ {
+ writer.Write(this.numbers[i, j] + (j == this.Columns - 1 ? string.Empty : " "));
+ }
+
+ if (i < this.Rows - 1)
+ {
+ writer.WriteLine();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/MatrixMultiplier.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/MatrixMultiplier.cs
new file mode 100644
index 0000000..297df56
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/MatrixMultiplier.cs
@@ -0,0 +1,104 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication;
+
+///
+/// A class for performing matrix multiplication in sequential and parallel ways.
+///
+public static class MatrixMultiplier
+{
+ ///
+ /// Performs sequential multiplication of two matrices(AxB).
+ ///
+ /// The first matrix.
+ /// The second matrix.
+ /// The resulting matrix.
+ /// It is thrown if the number of columns of the first
+ /// matrix is not equal to the number of rows of the second.
+ ///
+ public static Matrix SequentialMultiplication(Matrix a, Matrix b)
+ {
+ if (a.Columns != b.Rows)
+ {
+ throw new InvalidDataException("Умножение невозможно(количество столбцов первой матрицы не равно количеству строк второй)");
+ }
+
+ int[,] resultData = new int[a.Rows, b.Columns];
+ for (int i = 0; i < a.Rows; ++i)
+ {
+ for (int j = 0; j < b.Columns; j++)
+ {
+ int sum = 0;
+ for (int k = 0; k < a.Columns; k++)
+ {
+ sum += a[i, k] * b[k, j];
+ }
+
+ resultData[i, j] = sum;
+ }
+ }
+
+ return new Matrix(resultData);
+ }
+
+ ///
+ /// Performs parallel multiplication of two matrices(AxB).
+ ///
+ /// The first matrix.
+ /// The second matrix.
+ /// Number of threads.
+ /// The resulting matrix.
+ /// It is thrown if the number of columns of the first
+ /// matrix is not equal to the number of rows of the second.
+ ///
+ public static Matrix ParallelMultiplication(Matrix a, Matrix b, int numThreads)
+ {
+ if (a.Columns != b.Rows)
+ {
+ throw new InvalidDataException("Умножение невозможно(количество столбцов первой матрицы не равно количеству строк второй)");
+ }
+
+ int[,] resultData = new int[a.Rows, b.Columns];
+
+ int actualNumOfThread = Math.Min(a.Rows, numThreads);
+ Thread[] threads = new Thread[actualNumOfThread];
+ int rowsForThread = a.Rows / actualNumOfThread;
+
+ for (int i = 0; i < actualNumOfThread; ++i)
+ {
+ int startRow = i * rowsForThread;
+ int endRow = (i == actualNumOfThread - 1) ? a.Rows : (i + 1) * rowsForThread;
+
+ threads[i] = new Thread(() =>
+ {
+ for (int row = startRow; row < endRow; row++)
+ {
+ for (int columns = 0; columns < b.Columns; columns++)
+ {
+ int sum = 0;
+ for (int k = 0; k < a.Columns; ++k)
+ {
+ sum += a[row, k] * b[k, columns];
+ }
+
+ resultData[row, columns] = sum;
+ }
+ }
+ });
+ }
+
+ foreach (var thread in threads)
+ {
+ thread.Start();
+ }
+
+ foreach (var thread in threads)
+ {
+ thread.Join();
+ }
+
+ return new Matrix(resultData);
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/MatrixUserInterface.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/MatrixUserInterface.cs
new file mode 100644
index 0000000..942eb6a
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/MatrixUserInterface.cs
@@ -0,0 +1,117 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace ParallelMatrixMultiplication;
+
+using System.Diagnostics;
+
+///
+/// A user interface class for working with matrix multiplication.
+///
+public static class MatrixUserInterface
+{
+ ///
+ /// Loads matrices from files, performs sequential and parallel multiplication,
+ /// and saves the results to files, as well as additionally measures execution time.
+ ///
+ /// The path to the first matrix.
+ /// The path to the second matrix.
+ /// The path to the sequential result matrix.
+ /// The path to the parallel result matrix.
+ public static void LoadFromFileAndMultiply(string pathA, string pathB, string sequentialSavePath, string parallelSavePath)
+ {
+ Matrix first = Matrix.LoadFromFile(pathA);
+ Matrix second = Matrix.LoadFromFile(pathB);
+
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ Matrix sequentialResult = MatrixMultiplier.SequentialMultiplication(first, second);
+ stopwatch.Stop();
+ Console.WriteLine($"\nПоследовательное умножение завершено. Время: {stopwatch.ElapsedMilliseconds} мс");
+
+ sequentialResult.SaveToFile(sequentialSavePath);
+
+ int numOfThreads = Environment.ProcessorCount;
+ Console.WriteLine($"\nПараллельное умножение c {numOfThreads} потоками:");
+ stopwatch.Restart();
+ Matrix parallelResult = MatrixMultiplier.ParallelMultiplication(first, second, numOfThreads);
+ stopwatch.Stop();
+ Console.WriteLine($"\nПараллельное уммножение завершено. Время: {stopwatch.ElapsedMilliseconds} мс");
+
+ parallelResult.SaveToFile(parallelSavePath);
+ }
+
+ ///
+ /// Performs performance testing of sequential and parallel matrix multiplication
+ /// for various matrix sizes with a set number of runs.
+ ///
+ /// The number of runs for each test.
+ public static void UsersMatrixTests(int n)
+ {
+ var testCases = new List<(int RowsA, int ColumnsA, int RowsB, int ColumnsB)>()
+ {
+ (100, 100, 100, 100),
+ (200, 200, 200, 200),
+ (300, 300, 300, 300),
+ (400, 400, 400, 400),
+ (500, 500, 500, 500),
+ };
+
+ Console.WriteLine($"Проведение тестирования с {n} запусками");
+ Console.WriteLine("\nРазмеры матриц | " +
+ "Матожидание(последовательное) | " +
+ "СКО(последовательное) | " +
+ "Матожидание(параллельное) | " +
+ "СКО(параллельное) \n");
+
+ foreach (var testCase in testCases)
+ {
+ int rowsA = testCase.RowsA;
+ int columnsA = testCase.ColumnsA;
+ int rowsB = testCase.RowsB;
+ int columnsB = testCase.ColumnsB;
+
+ Matrix matrixA = Matrix.GenerateRandomMatrix(rowsA, columnsA);
+ Matrix matrixB = Matrix.GenerateRandomMatrix(rowsB, columnsB);
+
+ var sequentialTimes = new List();
+ var parallelTimes = new List();
+
+ int numOfThreads = Environment.ProcessorCount;
+
+ for (int i = 0; i < n; ++i)
+ {
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ MatrixMultiplier.SequentialMultiplication(matrixA, matrixB);
+ stopwatch.Stop();
+ sequentialTimes.Add(stopwatch.Elapsed.TotalMilliseconds);
+
+ stopwatch.Restart();
+ MatrixMultiplier.ParallelMultiplication(matrixA, matrixB, numOfThreads);
+ stopwatch.Stop();
+ parallelTimes.Add(stopwatch.Elapsed.TotalMilliseconds);
+ }
+
+ double sequentialExpectation = CalculateMathematicalExpectation(sequentialTimes);
+ double parallelExpectation = CalculateMathematicalExpectation(parallelTimes);
+
+ double sequentialStandardDeviation = CalculateStandardDeviation(sequentialTimes, sequentialExpectation);
+ double parallelStandardDeviation = CalculateStandardDeviation(parallelTimes, parallelExpectation);
+
+ Console.WriteLine($"{rowsA}x{columnsA} * {rowsB}x{columnsB} | {sequentialExpectation:F2} мс | {sequentialStandardDeviation:F2} | {parallelExpectation:F2} | {parallelStandardDeviation:F2}\n");
+ }
+ }
+
+ private static double CalculateMathematicalExpectation(List values) => values.Sum() / values.Count;
+
+ private static double CalculateStandardDeviation(List values, double expectation)
+ {
+ double sumOfSquares = 0;
+ foreach (double value in values)
+ {
+ sumOfSquares += (value - expectation) * (value - expectation);
+ }
+
+ return Math.Sqrt(sumOfSquares / values.Count);
+ }
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/ParallelMatrixMultiplication.csproj b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/ParallelMatrixMultiplication.csproj
new file mode 100644
index 0000000..81e1be1
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/ParallelMatrixMultiplication.csproj
@@ -0,0 +1,25 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/Program.cs b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/Program.cs
new file mode 100644
index 0000000..7ff2eb9
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/Program.cs
@@ -0,0 +1,63 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+using ParallelMatrixMultiplication;
+
+args = Environment.GetCommandLineArgs().Skip(1).ToArray();
+
+if (args.Length == 0)
+{
+ Console.WriteLine("\n Укажите режим работы ('load' или 'matrixTest')");
+ return;
+}
+var (choice, parameters) = ArgumentParser.Parse(args);
+
+try
+{
+ switch (choice)
+ {
+ case "load":
+ if (parameters.Length < 4)
+ {
+ Console.WriteLine("Недостаточно аргументов. (load )");
+ return;
+ }
+
+ string pathA = parameters[0];
+ string pathB = parameters[1];
+ string sequentialSavePath = parameters[2];
+ string parallelSavePath = parameters[3];
+
+ ArgumentNullException.ThrowIfNullOrEmpty(pathA);
+ ArgumentNullException.ThrowIfNullOrEmpty(pathB);
+ ArgumentNullException.ThrowIfNullOrEmpty(sequentialSavePath);
+ ArgumentNullException.ThrowIfNullOrEmpty(parallelSavePath);
+ MatrixUserInterface.LoadFromFileAndMultiply(pathA, pathB, sequentialSavePath, parallelSavePath);
+ break;
+
+ case "matrixtest":
+ if (parameters.Length < 1)
+ {
+ Console.WriteLine("Недостаточно аргументов. (matrixtest )");
+ return;
+ }
+
+ if (!int.TryParse(parameters[0], out int n) || n <= 0)
+ {
+ Console.WriteLine("Неверное количество запусков. Ожидается целое положительное число");
+ return;
+ }
+
+ MatrixUserInterface.UsersMatrixTests(n);
+ break;
+
+ default:
+ Console.WriteLine("\nНеизвестный ввод. Ожидается load или matrixtest\n");
+ break;
+ }
+}
+catch (Exception ex)
+{
+ Console.WriteLine($"Произошла ошибка: {ex.Message}");
+}
\ No newline at end of file
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/resultOfTheExperiment.png b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/resultOfTheExperiment.png
new file mode 100644
index 0000000..174583c
Binary files /dev/null and b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/resultOfTheExperiment.png differ
diff --git a/ParallelMatrixMultiplication/ParallelMatrixMultiplication/stylecop.json b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/stylecop.json
new file mode 100644
index 0000000..ce12f73
--- /dev/null
+++ b/ParallelMatrixMultiplication/ParallelMatrixMultiplication/stylecop.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "documentationRules": {
+ "companyName": "Kalinin Andrew",
+ "copyrightText": "Copyright (c) {companyName}. All rights reserved."
+ }
+ }
+}