Убрал ненужный код, ищу методы оптимизации

This commit is contained in:
AZEN-SGG 2025-04-09 15:45:55 +03:00
parent 191b0205e6
commit cb3f70cbd6
7 changed files with 123 additions and 136 deletions

View file

@ -1,29 +1,21 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "array_io.h" #include "array_io.h"
#include "io_status.h"
io_status read_matrix(double *a, int n, const char *name, bool transpose) io_status read_matrix(double *a, int n, const char *name)
{ {
int i, j; int i, j;
FILE *fp; FILE *fp;
if (!(fp = fopen(name, "r"))) return ERROR_OPEN; if (!(fp = fopen(name, "r"))) return ERROR_OPEN;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
for (j = 0; j < n; j++) for (j = 0; j < n; j++)
{ if (fscanf(fp, "%lf", a + i * n + j) != 1)
if (transpose) {fclose(fp); return ERROR_READ;}
{
if (fscanf(fp, "%lf", a + j * n + i) != 1)
{fclose(fp); return ERROR_READ;}
} else
if (fscanf(fp, "%lf", a + i * n + j) != 1)
{fclose(fp); return ERROR_READ;}
}
fclose(fp); fclose(fp);
return SUCCESS; return SUCCESS;
} }
void print_matrix(const double *a, int n, int p, bool transpose) void print_matrix(const double *a, int n, int p)
{ {
int np = (n > p ? p : n); int np = (n > p ? p : n);
int i, j; int i, j;
@ -31,17 +23,12 @@ void print_matrix(const double *a, int n, int p, bool transpose)
for (i = 0; i < np; i++) for (i = 0; i < np; i++)
{ {
for (j = 0; j < np; j++) for (j = 0; j < np; j++)
{ printf(" %10.3e", a[i * n + j]);
if (transpose)
printf(" %10.3e", a[j * n + i]);
else
printf(" %10.3e", a[i * n + j]);
}
printf("\n"); printf("\n");
} }
} }
void init_matrix(double *a, int n, int k, bool transpose) void init_matrix(double *a, int n, int k)
{ {
double (*q)(int, int, int, int); double (*q)(int, int, int, int);
double (*f[])(int, int, int, int) = {f1, f2, f3, f4}; double (*f[])(int, int, int, int) = {f1, f2, f3, f4};
@ -49,15 +36,9 @@ void init_matrix(double *a, int n, int k, bool transpose)
q = f[k-1]; q = f[k-1];
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
for (j = 0; j < n; j++) for (j = 0; j < n; j++)
{ a[i * n + j] = q(n, n, i+1, j+1);
if (transpose)
a[i * n + j] = q(n, n, j+1, i+1);
else
a[i * n + j] = q(n, n, j+1, i+1);
}
} }
void init_identity_matrix(double *a, int n) void init_identity_matrix(double *a, int n)
{ {
a = memset(a, 0, n * n * sizeof(double)); a = memset(a, 0, n * n * sizeof(double));
@ -66,12 +47,12 @@ void init_identity_matrix(double *a, int n)
a[i*n + i] = 1.0; a[i*n + i] = 1.0;
} }
int read_or_init_matrix(double *a, char *name, int k, int n, bool transpose) int read_or_init_matrix(double *a, char *name, int k, int n)
{ {
if (name) if (name)
{ /* из файла */ { /* из файла */
io_status ret; io_status ret;
ret = read_matrix(a, n, name, transpose); ret = read_matrix(a, n, name);
do { do {
switch (ret) switch (ret)
{ {
@ -85,7 +66,7 @@ int read_or_init_matrix(double *a, char *name, int k, int n, bool transpose)
} }
return 3; return 3;
} while (0); } while (0);
} else init_matrix(a, n, k, transpose); } else init_matrix(a, n, k);
return 0; return 0;
} }

View file

@ -1,14 +1,13 @@
#ifndef ARRAY_IO_H #ifndef ARRAY_IO_H
#define ARRAY_IO_H #define ARRAY_IO_H
#include <stdbool.h>
#include "io_status.h" #include "io_status.h"
#include "init_f.h" #include "init_f.h"
io_status read_matrix(double *a, int n, const char *name, bool transpose); io_status read_matrix(double *a, int n, const char *name);
void print_matrix(const double *a, int n, int p, bool transpose); void print_matrix(const double *a, int n, int p);
void init_matrix(double *a, int n, int k, bool transpose); void init_matrix(double *a, int n, int k);
void init_identity_matrix(double *a, int n); void init_identity_matrix(double *a, int n);
int read_or_init_matrix(double *a, char *name, int k, int n, bool transpose); int read_or_init_matrix(double *a, char *name, int k, int n);
#endif #endif

View file

@ -1,6 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <time.h> #include <time.h>
#include "array_io.h" #include "array_io.h"
#include "io_status.h" #include "io_status.h"
@ -48,7 +47,7 @@ int main(int argc, char *argv[])
return 2; return 2;
} }
res = read_or_init_matrix(a, name, k, n, true); res = read_or_init_matrix(a, name, k, n);
if (res) if (res)
{ {
free(a); free(a);
@ -64,7 +63,7 @@ int main(int argc, char *argv[])
c[i] = i; c[i] = i;
printf("Initial matrix:\n"); printf("Initial matrix:\n");
print_matrix(a, n, p, true); print_matrix(a, n, p);
t = clock(); t = clock();
res = t14_solve(n, a, x, c); res = t14_solve(n, a, x, c);
@ -80,7 +79,7 @@ int main(int argc, char *argv[])
return 4; return 4;
} }
res = read_or_init_matrix(a, name, k, n, false); res = read_or_init_matrix(a, name, k, n);
if (res) if (res)
{ {
free(a); free(a);
@ -94,7 +93,7 @@ int main(int argc, char *argv[])
r2 = get_r2(n, a, x); r2 = get_r2(n, a, x);
printf("Inverse matrix:\n"); printf("Inverse matrix:\n");
print_matrix(x, n, p, false); print_matrix(x, n, p);
printf("%s : Task = %d Res1 = %e Res2 = %e Elapsed = %.2f K = %d N = %d\n", argv[0], task, r1, r2, t, k, n); printf("%s : Task = %d Res1 = %e Res2 = %e Elapsed = %.2f K = %d N = %d\n", argv[0], task, r1, r2, t, k, n);
free(a); free(a);

View file

@ -19,7 +19,6 @@ void matvec_mul(int n, const double * restrict A, const double * restrict x, dou
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
double sum = 0; double sum = 0;
for (int j = 0; j < n; j++) for (int j = 0; j < n; j++)
sum += A[i * n + j] * x[j]; sum += A[i * n + j] * x[j];
x_k[i] = sum; x_k[i] = sum;

View file

@ -1,15 +1,19 @@
#include "solve.h" #include "solve.h"
#include "io_status.h" #include "io_status.h"
#include <float.h>
#include <math.h>
#include "array_io.h" #include "array_io.h"
#include "matrix.h" #include "matrix.h"
#include <float.h>
#include <math.h>
#include <stdio.h> #include <stdio.h>
// c - changes in rows // c - changes in rows
int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c) int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
{ {
double norm = get_matrix_norm(n, A); double norm = get_matrix_norm(n, A);
double eps = DBL_EPSILON*norm;
if (norm < DBL_EPSILON)
return SINGULAR;
// Проходимся по главным минорам // Проходимся по главным минорам
for (int k = 0; k < n; ++k) { for (int k = 0; k < n; ++k) {
@ -28,9 +32,11 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
} }
} }
// printf("\n------- K = %d -------\n", k);
// printf("Maximum = %lf i = %d j = %d\n", maximum, max_i, max_j);
// Если максимальный по модулю элемент равен нулю, значит матрица вырождена // Если максимальный по модулю элемент равен нулю, значит матрица вырождена
if (fabs(maximum) < DBL_EPSILON * norm) if (fabs(maximum) < eps)
return SINGULAR; return SINGULAR;
// Меняем строки местами, если максимум находится не в k строке // Меняем строки местами, если максимум находится не в k строке
@ -67,93 +73,79 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
c[max_j] = c[k]; c[max_j] = c[k];
c[k] = swap_temp; c[k] = swap_temp;
for (int in = 0; in < n*n; in+=n) for (int i = 0; i < n; i++)
{ {
const int in = i*n;
double swap = A[in + k]; double swap = A[in + k];
A[in + k] = A[in + max_j]; A[in + k] = A[in + max_j];
A[in + max_j] = swap; A[in + max_j] = swap;
} }
} }
// printf("BEFORE GAUSS\n");
// printf("Original matrix:\n");
// print_matrix(A, n, n);
// printf("Inverse matrix:\n");
// print_matrix(X, n, n);
gauss_inverse(n, k, A, X); gauss_inverse(n, k, A, X);
// printf("AFTER GAUSS\n");
// printf("Original matrix:\n");
// print_matrix(A, n, n);
// printf("Inverse matrix:\n");
// print_matrix(X, n, n);
} }
gauss_back_substitution(n, A, X); gauss_back_substitution(n, A, X);
// Возвращаем строки назад
for (int k = 0; k < n; ++k) for (int k = 0; k < n; ++k)
{ {
int pnt_cur = c[k]; const int kn = k*n;
int i = c[k];
if (pnt_cur != k) while (i != k)
{ {
int pnt_nxt = 0; const int in = i*n;
const int swap_int = c[i];
c[i] = i;
i = swap_int;
for (int j = 0; j < n; ++j) for (int j = 0; j < n; ++j)
{ {
int loc_cur = pnt_cur; double swap_temp = X[in+j];
double temp_cur = X[k*n + j]; X[in+j] = X[kn+j];
double temp_nxt = 0; X[kn+j] = swap_temp;
do {
temp_nxt = X[loc_cur*n + j];
X[loc_cur*n + j] = temp_cur;
temp_cur = temp_nxt;
loc_cur = c[loc_cur];
} while (loc_cur != k);
X[k*n + j] = temp_cur;
} }
do {
pnt_nxt = c[pnt_cur];
c[pnt_cur] = pnt_cur;
pnt_cur = pnt_nxt;
} while (pnt_nxt != k);
c[k] = k;
} }
} }
return 0; return 0;
} }
// Прямой ход Го ----- йда
void gauss_inverse(const int n, const int k, double * restrict A, double * restrict X) void gauss_inverse(const int n, const int k, double * restrict A, double * restrict X)
{ {
const int kn = k*n; const int kn = k*n;
const int kk = kn + k; const int kk = kn + k;
const double inv_akk = 1./A[kn + k]; const double inv_akk = 1./A[kk];
A[kn + k] = 1.;
for (int ij = kn; ij <= kn+k; ++ij) for (int ij = kk+1; ij < kn+n; ij++)
{ A[ij] *= inv_akk;
double xij = X[ij];
if (fabs(xij) > DBL_EPSILON) X[ij] = xij*inv_akk;
}
for (int ij = kn + k+1; ij < kn+n; ++ij) for (int ij = kn; ij < kn+n; ij++)
{ X[ij] *= inv_akk;
double aij = A[ij], xij = X[ij];
if (fabs(aij) > DBL_EPSILON) A[ij] = aij*inv_akk;
if (fabs(xij) > DBL_EPSILON) X[ij] = xij*inv_akk;
}
for (int i = k+1; i < n; ++i) for (int i = k+1; i < n; ++i)
{ {
const int in = i*n; const int in = i*n;
const double aik = A[in + k]; const double aik = A[in + k];
A[in + k] = 0;
X[in + k] -= X[kk] * aik;
for (int j = 0; j < k; ++j) for (int ij = in+k+1, kj = kk+1; ij < in+n; ij++, kj++)
X[in + j] -= X[kn + j] * aik; A[ij] -= A[kj] * aik;
for (int j = k+1; j < n; ++j) for (int ij = in, kj = kn; kj < kn + n; ij++, kj++)
{ X[ij] -= X[kj] * aik;
A[in + j] -= A[kn + j] * aik;
X[in + j] -= X[kn + j] * aik;
}
} }
} }
@ -169,11 +161,16 @@ void gauss_back_substitution(const int n, double * restrict A, double * restrict
{ {
const int in = i*n; const int in = i*n;
const double aik = A[in + k]; const double aik = A[in + k];
A[in + k] = 0;
for (int j = 0; j < n; ++j) for (int j = 0; j < n; ++j)
X[in + j] -= X[kn + j] * aik; X[in + j] -= X[kn + j] * aik;
} }
// printf("\n------- K = %d -------\n", k);
// printf("Original matrix:\n");
// print_matrix(A, n, n);
// printf("Inverse matrix:\n");
// print_matrix(X, n, n);
} }
} }

View file

@ -36,7 +36,7 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
// printf("Maximum = %lf i = %d j = %d\n", maximum, max_i, max_j); // printf("Maximum = %lf i = %d j = %d\n", maximum, max_i, max_j);
// Если максимальный по модулю элемент равен нулю, значит матрица вырождена // Если максимальный по модулю элемент равен нулю, значит матрица вырождена
if (maximum < eps) if (fabs(maximum) < eps)
return SINGULAR; return SINGULAR;
// Меняем строки местами, если максимум находится не в k строке // Меняем строки местами, если максимум находится не в k строке
@ -45,17 +45,22 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
int kn = k*n; int kn = k*n;
int in = max_i*n; int in = max_i*n;
for (int mj = in, kj = kn; mj < in+n; ++mj, ++kj) for (int i = 0; i < k; ++i)
{ {
double swap = X[mj]; int kni = kn+i, ini = in+i;
X[mj] = X[kj]; double swap = X[kni];
X[kj] = swap; X[kni] = X[ini];
X[ini] = swap;
} }
for (int i = k; i < n; ++i) for (int i = k; i < n; ++i)
{ {
int kni = kn+i, ini = in+i; int kni = kn+i, ini = in+i;
double swap = A[kni]; double swap = X[kni];
X[kni] = X[ini];
X[ini] = swap;
swap = A[kni];
A[kni] = A[ini]; A[kni] = A[ini];
A[ini] = swap; A[ini] = swap;
} }
@ -82,7 +87,7 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
// printf("Inverse matrix:\n"); // printf("Inverse matrix:\n");
// print_matrix(X, n, n); // print_matrix(X, n, n);
gauss_inverse(n, k, A, X, eps); gauss_inverse(n, k, A, X);
// printf("AFTER GAUSS\n"); // printf("AFTER GAUSS\n");
// printf("Original matrix:\n"); // printf("Original matrix:\n");
@ -93,8 +98,29 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
gauss_back_substitution(n, A, X); gauss_back_substitution(n, A, X);
// Возвращаем строки назад
for (int k = 0; k < n; ++k) for (int k = 0; k < n; ++k)
{
const int kn = k*n;
int i = c[k];
while (i != k)
{
const int in = i*n;
const int swap_int = c[i];
c[i] = i;
i = swap_int;
for (int ij = in, kj = kn; ij < in+n; ++ij, ++kj)
{
double swap_temp = X[ij];
X[ij] = X[kj];
X[kj] = swap_temp;
}
}
}
// Возвращаем строки назад
/* for (int k = 0; k < n; ++k)
{ {
int pnt_cur = c[k]; int pnt_cur = c[k];
@ -127,40 +153,23 @@ int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c)
c[k] = k; c[k] = k;
} }
} }*/
return 0; return 0;
} }
// Прямой ход Го ----- йда // Прямой ход Го ----- йда
void gauss_inverse(const int n, const int k, double * restrict A, double * restrict X, double eps) void gauss_inverse(const int n, const int k, double * restrict A, double * restrict X)
{ {
const int kn = k*n; const int kn = k*n;
const int kk = kn + k; const int kk = kn + k;
const double inv_akk = 1./A[kk]; const double inv_akk = 1./A[kk];
if (eps > DBL_EPSILON) for (int ij = kk+1; ij < kn+n; ij++)
eps = DBL_EPSILON; A[ij] *= inv_akk;
// Делим на A[k][k] for (int ij = kn; ij < kn+n; ij++)
for (int kj = kk+1; kj < kn+n; kj++) X[ij] *= inv_akk;
A[kj] *= inv_akk;
// Меняем обратную матрицу
for (int j = 0; j < n; ++j)
{
const int BS = 32;
double xkj = X[kn + j];
if (fabs(xkj) <= eps)
continue;
xkj *= inv_akk;
X[kn + j] = xkj;
for (int i_block = k + 1; i_block < n; i_block += BS)
for (int i = i_block; i < i_block + BS && i < n; ++i)
X[i * n + j] -= xkj * A[i * n + k];
}
for (int i = k+1; i < n; ++i) for (int i = k+1; i < n; ++i)
{ {
@ -169,6 +178,9 @@ void gauss_inverse(const int n, const int k, double * restrict A, double * restr
for (int ij = in+k+1, kj = kk+1; ij < in+n; ij++, kj++) for (int ij = in+k+1, kj = kk+1; ij < in+n; ij++, kj++)
A[ij] -= A[kj] * aik; A[ij] -= A[kj] * aik;
for (int ij = in, kj = kn; kj < kn + n; ij++, kj++)
X[ij] -= X[kj] * aik;
} }
} }

View file

@ -2,7 +2,7 @@
#define SOLVE_H #define SOLVE_H
int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c); int t14_solve(int n, double * restrict A, double * restrict X, int * restrict c);
void gauss_inverse(const int n, const int k, double * restrict A, double * restrict X, double eps); void gauss_inverse(const int n, const int k, double * restrict A, double * restrict X);
void gauss_back_substitution(const int n, double * restrict A, double * restrict X); void gauss_back_substitution(const int n, double * restrict A, double * restrict X);
#endif #endif