omp/MatrixExtensions.cs
2025-04-13 23:05:53 +03:00

197 lines
5.1 KiB
C#

using System.ComponentModel;
namespace omp
{
public static class MatrixExtensions
{
public static void Print(this double[,] a)
{
int rows = a.GetLength(0);
int columns = a.GetLength(1);
Console.WriteLine("Matrix of size {0}x{1}:", rows, columns);
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < columns; ++j)
{
Console.Write("\t{0}", a[i, j]);
}
Console.WriteLine("");
}
}
public static void SaveToFile(this double[,] a, string filePath)
{
int rows = a.GetLength(0);
int cols = a.GetLength(0);
using (var stream = new FileStream(filePath, FileMode.Create))
using (var writer = new BinaryWriter(stream))
{
unsafe
{
fixed (double* ptr = &a[0, 0])
{
byte* bytePtr = (byte*)ptr;
int byteCount = rows * cols * sizeof(double);
writer.Write(new ReadOnlySpan<byte>(bytePtr, byteCount));
}
}
}
}
public static double Adj(this double[,] a, int i, int j)
{
double sgn = ((i + j) % 2 == 0) ? 1 : -1;
return sgn * Det(Minor(a, j, i));
}
public static double[,] Minor(this double[,] a, int i, int j)
{
int rows = a.GetLength(0);
int columns = a.GetLength(1);
double[,] minor = new double[rows - 1, columns - 1];
int k = 0;
int l;
for (int r = 0; r < rows; ++r)
{
if (r == i)
{
continue;
}
l = 0;
for (int c = 0; c < columns; ++c)
{
if (c == j)
{
continue;
}
minor[k, l] = a[r, c];
l++;
}
k++;
}
return minor;
}
public static double Det(this double[,] a)
{
int n = a.GetLength(0);
switch (n)
{
case 1:
return a[0, 0];
case 2:
return Det2(a);
case 3:
return Det3(a);
default:
double det = 0;
double sgn;
for (int j = 0; j < n; ++j)
{
sgn = (j % 2 == 0) ? 1 : -1;
det += sgn * a[0, j] * Det(Minor(a, 0, j));
}
return det;
}
}
public static double Det2(this double[,] a)
{
return a[0, 0] * a[1, 1] - a[0, 1] * a[1, 0];
}
public static double Det3(double[,] a)
{
if (a.GetLength(0) != 3 || a.GetLength(1) != 3)
throw new ArgumentException("Matrix must be 3x3");
return
a[0, 0] * a[1, 1] * a[2, 2]
+ a[0, 1] * a[1, 2] * a[2, 0]
+ a[0, 2] * a[1, 0] * a[2, 1]
- a[0, 2] * a[1, 1] * a[2, 0]
- a[0, 0] * a[1, 2] * a[2, 1]
- a[2, 2] * a[0, 1] * a[1, 0];
}
public static double[,] MultTrans(this double[,] a)
{
int rows = a.GetLength(0);
int columns = a.GetLength(1);
double[,] r = new double[rows, rows];
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < rows; ++j)
{
for (int k = 0; k < columns; ++k)
{
r[i, j] += a[i, k] * a[j, k];
}
}
}
return r;
}
public static (double Min, double Max) MinMax(this double[,] a)
{
double min = double.MaxValue;
double max = double.MinValue;
object MMLock = new();
Parallel.For(0, a.GetLength(0), i =>
{
double localMin = double.MaxValue;
double localMax = double.MinValue;
for (int j = 0; j < a.GetLength(1); ++j)
{
if (a[i, j] < localMin)
{
localMin = a[i, j];
}
if (a[i, j] > localMax)
{
localMax = a[i, j];
}
}
lock (MMLock)
{
if (localMin < min)
{
min = localMin;
}
if (localMax > max)
{
max = localMax;
}
}
});
return (min, max);
}
}
}