ngspice/src/maths/dense/dense.c

1277 lines
24 KiB
C

#include "dense.h"
#include "denseinlines.h"
#include "ngspice/ngspice.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "ngspice/bool.h"
#include "ngspice/iferrmsg.h"
void showmat(Mat* A) {
if (A->row > 0 && A->col > 0) {
printf("[");
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (j < A->col) {
printf("%f\t", A->d[i][j]);
}
else {
printf("%f", A->d[i][j]);
}
}
if (i < A->row) {
printf("\n");
}
else {
printf("]\n");
}
}
printf("\n");
}
else {
printf("[]");
}
}
void showcmat(CMat* A) {
if (A->row > 0 && A->col > 0) {
printf("[");
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (j < A->col) {
printf("%f+i%f\t", A->d[i][j].re, A->d[i][j].im);
}
else {
printf("%f+i%f\t", A->d[i][j].re, A->d[i][j].im);
}
}
if (i < A->row) {
printf("\n");
}
else {
printf("]\n");
}
}
printf("\n");
}
else {
printf("[]");
}
}
CMat* newcmat(int r, int c, double dr, double di) {
CMat* M = (CMat*)tmalloc(sizeof(CMat));
if (M == NULL) return NULL;
M->row = r; M->col = c;
M->d = (cplx**)tmalloc(sizeof(cplx*) * r);
if (M->d == NULL) {
tfree(M); return NULL;
}
for (int i = 0; i < r; i++)
M->d[i] = (cplx*)tmalloc(sizeof(cplx) * c);
for (int i = 0; i < M->row; i++) {
for (int j = 0; j < M->col; j++) {
M->d[i][j].re = dr;
M->d[i][j].im = di;
}
}
return M;
}
void init(Mat* A, double d)
{
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
A->d[i][j] = d;
}
}
}
void cinit(CMat* A, double dr, double di)
{
cplx ci;
ci.re = dr;
ci.im = di;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
A->d[i][j] = ci;
}
}
}
CMat* newcmatnoinit(int r, int c) {
CMat* M = (CMat*)tmalloc(sizeof(CMat));
if (M == NULL) return NULL;
M->row = r; M->col = c;
M->d = (cplx**)tmalloc(sizeof(cplx*) * r);
for (int i = 0; i < r; i++)
M->d[i] = (cplx*)tmalloc(sizeof(cplx) * c);
return M;
}
Mat* newmat(int r, int c, double d) {
Mat* M = (Mat*)tmalloc(sizeof(Mat));
if (M == NULL) return NULL;
M->row = r; M->col = c;
M->d = (double**)tmalloc(sizeof(double*) * r);
for (int i = 0; i < r; i++)
M->d[i] = (double*)tmalloc(sizeof(double) * c);
for (int i = 0; i < M->row; i++) {
for (int j = 0; j < M->col; j++) {
M->d[i][j] = d;
}
}
return M;
}
Mat* newmatnoinit(int r, int c) {
Mat* M = (Mat*)tmalloc(sizeof(Mat));
if (M == NULL) return NULL;
M->row = r; M->col = c;
M->d = (double**)tmalloc(sizeof(double*) * r);
for (int i = 0; i < r; i++)
M->d[i] = (double*)tmalloc(sizeof(double) * c);
return M;
}
void resizemat(Mat* A, int r, int c)
{
if (A == NULL) return;
if ((A->row == r) && (A->col == c))
return;
for (int ri = 0; ri < A->row; ri++)
tfree(A->d[ri]);
if (A->d != NULL)
tfree(A->d);
A->row = r; A->col = c;
A->d = (double**)tmalloc(sizeof(double*) * r);
if (A->d == NULL) return;
for (int i = 0; i < r; i++)
A->d[i] = (double*)tmalloc(sizeof(double) * c);
}
void resizecmat(CMat* A, int r, int c)
{
if (A == NULL) return;
if ((A->row == r) && (A->col == c))
return;
for (int ri = 0; ri < A->row; ri++)
tfree(A->d[ri]);
if (A->d != NULL)
tfree(A->d);
A->row = r; A->col = c;
A->d = (cplx**)tmalloc(sizeof(cplx*) * r);
if (A->d == NULL) return;
for (int i = 0; i < r; i++)
A->d[i] = (cplx*)tmalloc(sizeof(cplx) * c);
}
void freecmat(CMat* A) {
if (A == NULL) return;
for (int r = 0; r < A->row; r++)
tfree(A->d[r]);
if (A->d!=NULL)
tfree(A->d);
tfree(A);
}
void freemat(Mat* A) {
if (A == NULL) return;
for (int r = 0; r < A->row; r++)
tfree(A->d[r]);
if (A->d!=NULL)
tfree(A->d);
tfree(A);
}
CMat* ceye(int n) {
CMat* I = newcmat(n, n, 0,0);
for (int i = 0; i < n; i++) {
I->d[i][i].re = 1;
}
return I;
}
Mat* eye(int n) {
Mat* I = newmat(n, n, 0);
for (int i = 0; i < n; i++) {
I->d[i][i] = 1;
}
return I;
}
Mat* zeros(int r, int c) {
Mat* Z = newmat(r, c, 0);
return Z;
}
CMat* czeros(int r, int c) {
CMat* Z = newcmat(r, c, 0,0);
return Z;
}
Mat* ones(int r, int c) {
Mat* O = newmat(r, c, 1);
return O;
}
CMat* cones(int r, int c) {
CMat* O = newcmat(r, c, 1,0);
return O;
}
Mat* randm(int r, int c, double l, double u) {
Mat* R = newmatnoinit(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
double rx = ((double)rand()) / ((double)RAND_MAX);
R->d[i][j] = l + (u - l) * rx;
}
}
return R;
}
CMat* randcm(int r, int c, double l, double u) {
CMat* R = newcmatnoinit(r, c);
double ks = u - l;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
setcplx(&(R->d[i][j]),
l + ks * ((double)rand()) / ((double)RAND_MAX),
l + ks * ((double)rand()) / ((double)RAND_MAX));
}
}
return R;
}
double get(Mat* M, int r, int c) {
double d = M->d[r][c];
return d;
}
cplx getcplx(CMat* M, int r, int c)
{
return M->d[r][c];
}
void set(Mat* M, int r, int c, double d) {
M->d[r][c] = d;
}
void setc(CMat* M, int r, int c, cplx d)
{
M->d[r][c] = d;
}
Mat* scalarmultiply(Mat* M, double c) {
Mat* B = newmatnoinit(M->row, M->col);
for (int i = 0; i < M->row; i++) {
for (int j = 0; j < M->col; j++) {
B->d[i][j] = M->d[i][j] * c;
}
}
return B;
}
CMat* cscalarmultiply(CMat* M, double c) {
CMat* B = newcmatnoinit(M->row, M->col);
for (int i = 0; i < M->row; i++) {
for (int j = 0; j < M->col; j++) {
cmultd(&(B->d[i][j]), M->d[i][j], c);
}
}
return B;
}
CMat* complexmultiply(CMat* M, cplx c) {
CMat* B = newcmatnoinit(M->row, M->col);
for (int i = 0; i < M->row; i++) {
for (int j = 0; j < M->col; j++) {
cmultc(&(B->d[i][j]), M->d[i][j], c);
}
}
return B;
}
int complexmultiplydest(CMat* M, cplx c, CMat* dest) {
for (int i = 0; i < M->row; i++) {
for (int j = 0; j < M->col; j++) {
cmultc(&(dest->d[i][j]), M->d[i][j], c);
}
}
return (OK);
}
Mat* sum(Mat* A, Mat* B) {
int r = A->row;
int c = A->col;
Mat* C = newmatnoinit(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
C->d[i][j] = A->d[i][j] + B->d[i][j];
}
}
return C;
}
CMat* csum(CMat* A, CMat* B) {
int r = A->row;
int c = A->col;
CMat* C = newcmatnoinit(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
caddc(&(C->d[i][j]), (A->d[i][j]), (B->d[i][j]));
}
}
return C;
}
Mat* minus(Mat* A, Mat* B) {
int r = A->row;
int c = A->col;
Mat* C = newmatnoinit(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
C->d[i][j] = A->d[i][j] - B->d[i][j];
}
}
return C;
}
CMat* cminus(CMat* A, CMat* B) {
int r = A->row;
int c = A->col;
CMat* C = newcmatnoinit(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
csubc(&(C->d[i][j]),
A->d[i][j],
B->d[i][j]);
}
}
return C;
}
Mat* submat(Mat* A, int r1, int r2, int c1, int c2) {
Mat* B = newmatnoinit(r2 - r1 + 1, c2 - c1 + 1);
for (int i = r1, id =0 ; i <= r2; i++, id++) {
for (int j = c1, jd=0; j <= c2; j++, jd++) {
B->d[id][jd] = A->d[i][j];
}
}
return B;
}
void submat2(Mat* A, Mat* B, int r1, int r2, int c1, int c2) {
for (int i = r1, id = 0; i <= r2; i++, id++) {
for (int j = c1, jd = 0; j <= c2; j++, jd++) {
B->d[id][jd] = A->d[i][j];
}
}
}
CMat* subcmat(CMat* A, int r1, int r2, int c1, int c2) {
CMat* B = newcmatnoinit(r2 - r1 + 1, c2 - c1 + 1);
int k = 0;
for (int i = r1; i <= r2; i++) {
for (int j = c1; j <= c2; j++) {
B->d[k++] = A->d[i * A->col + j];
}
}
return B;
}
void subcmat2(CMat* A, CMat* B, int r1, int r2, int c1, int c2) {
int k = 0;
for (int i = r1; i <= r2; i++) {
for (int j = c1; j <= c2; j++) {
B->d[k++] = A->d[i* A->col + j];
}
}
}
Mat* multiply(Mat* A, Mat* B) {
int r1 = A->row;
int r2 = B->row;
int c1 = A->col;
int c2 = B->col;
if (r1 == 1 && c1 == 1) {
Mat* C = scalarmultiply(B, A->d[0][0]);
return C;
}
else if (r2 == 1 && c2 == 1) {
Mat* C = scalarmultiply(A, B->d[0][0]);
return C;
}
Mat* C = newmatnoinit(r1, c2);
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
double de = 0;
for (int k = 0; k < r2; k++) {
de += A->d[i][k] * B->d[k][j];
}
C->d[i][j] = de;
}
}
return C;
}
CMat* cmultiply(CMat* A, CMat* B) {
int r1 = A->row;
int r2 = B->row;
int c1 = A->col;
int c2 = B->col;
if (r1 == 1 && c1 == 1) {
CMat* C = complexmultiply(B, A->d[0][0]);
return C;
}
else if (r2 == 1 && c2 == 1) {
CMat* C = complexmultiply(A, B->d[0][0]);
return C;
}
CMat* C = newcmatnoinit(r1, c2);
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
cplx de;
de.re = de.im = 0;
for (int k = 0; k < r2; k++) {
caddc(&de, de, cmultco(A->d[i][k], B->d[k][j]));
}
C->d[i][j] = de;
}
}
return C;
}
int cmultiplydest(CMat* A, CMat* B, CMat* dest) {
int r1 = A->row;
int r2 = B->row;
int c1 = A->col;
int c2 = B->col;
// r2 must be = c1
if (r1 == 1 && c1 == 1) {
complexmultiplydest(B, A->d[0][0],dest);
return (OK);
}
else if (r2 == 1 && c2 == 1) {
complexmultiplydest(A, B->d[0][0],dest);
return (OK);
}
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
cplx de;
de.re = de.im = 0;
for (int k = 0; k < r2; k++) {
caddc(&de, de, cmultco(A->d[i][k], B->d[k][j]));
}
dest->d[i][j] = de;
}
}
return (OK);
}
//-----------------------------------------
Mat* removerow(Mat* A, int r) {
Mat* B = newmatnoinit(A->row - 1, A->col);
int rowdest = 0;
for (int i = 0; i < A->row; i++) {
if (i!=r)
{
for (int j = 0; j < A->col; j++)
B->d[rowdest][j] = A->d[i][j];
rowdest++;
}
}
return B;
}
Mat* removecol(Mat* A, int c) {
Mat* B = newmatnoinit(A->row, A->col - 1);
int coldest = 0 ;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (j != c) {
B->d[i][coldest] = A->d[i][j];
coldest++;
}
}
}
return B;
}
void removerow2(Mat* A, Mat* B, int r) {
int rowdest = 0;
for (int i = 0; i < A->row; i++) {
if (i != r)
{
for (int j = 0; j < A->col; j++)
B->d[rowdest][j] = A->d[i][j];
rowdest++;
}
}
return;
}
void removecol2(Mat* A, Mat* B, int c) {
int coldest = 0;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (j != c) {
B->d[i][coldest] = A->d[i][j];
coldest++;
}
}
}
return;
}
CMat* cremoverow(CMat* A, int r) {
CMat* B = newcmatnoinit(A->row - 1, A->col);
int rowdest = 0;
for (int i = 0; i < A->row; i++) {
if (i != r)
{
for (int j = 0; j < A->col; j++)
B->d[rowdest][j] = A->d[i][j];
rowdest++;
}
}
return B;
}
CMat* cremovecol(CMat* A, int c) {
CMat* B = newcmatnoinit(A->row, A->col - 1);
int coldest = 0;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (j != c) {
B->d[i][coldest] = A->d[i][j];
coldest++;
}
}
}
return B;
}
void cremoverow2(CMat* A, CMat* B, int r) {
int rowdest = 0;
for (int i = 0; i < A->row; i++) {
if (i != r)
{
for (int j = 0; j < A->col; j++)
B->d[rowdest][j] = A->d[i][j];
rowdest++;
}
}
return;
}
void cremovecol2(CMat* A, CMat* B, int c) {
int coldest = 0;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (j != c) {
B->d[i][coldest] = A->d[i][j];
coldest++;
}
}
}
return;
}
Mat* transpose(Mat* A) {
Mat* B = newmatnoinit(A->col, A->row);
int k = 0;
for (int i = 0; i < A->col; i++) {
for (int j = 0; j < A->row; j++, k++) {
B->d[j][i] = A->d[i][j];
}
}
return B;
}
CMat* ctranspose(CMat* A) {
CMat* B = newcmatnoinit(A->col, A->row);
int k = 0;
for (int i = 0; i < A->col; i++) {
for (int j = 0; j < A->row; j++, k++) {
B->d[j][i] = A->d[i][j];
}
}
return B;
}
double det(Mat* M) {
int r = M->row;
int c = M->col;
if (r == 1 && c == 1) {
double d = M->d[0][0];
return d;
}
Mat* M1 = removerow(M, 1);
Mat* M2 = newmatnoinit(M->row - 1, M->col - 1);
double d = 0, si = +1;
for (int j = 0; j < M->col; j++) {
double cx = M->d[0][j];
removecol2(M1, M2, j);
d += si * det(M2) * cx;
si *= -1;
}
freemat(M1);
freemat(M2);
return d;
}
cplx cdet(CMat* M) {
int r = M->row;
int c = M->col;
if (r == 1 && c == 1) {
cplx d = M->d[0][0];
return d;
}
CMat* M1 = cremoverow(M, 0);
CMat* M2 = newcmatnoinit(M->row - 1, M->col - 1);
cplx d; double si = +1;
d.re = d.im = 0;
for (int j = 0; j < M->col; j++) {
cplx cx = M->d[0][j];
cremovecol2(M1, M2, j);
cplx d2 = cmultdo(cmultco(cdet(M2), cx), si);
caddc(&d, d, d2);
si = -si;
}
freecmat(M1);
freecmat(M2);
return d;
}
double trace(Mat* A) {
double d = 0;
for (int i = 0; i < A->row; i++) {
d += A->d[i][i];
}
return d;
}
cplx ctrace(CMat* A) {
cplx d;
d.re = d.im = 0;
for (int i = 0; i < A->row; i++) {
d=caddco(d, A->d[i][i]);
}
return d;
}
Mat* adjoint(Mat* A) {
Mat* B = newmatnoinit(A->row, A->col);
Mat* A1 = newmatnoinit(A->row - 1, A->col);
Mat* A2 = newmatnoinit(A->row - 1, A->col - 1);
for (int i = 0; i < A->row; i++) {
removerow2(A, A1, i);
for (int j = 0; j < A->col; j++) {
removecol2(A1, A2, j);
double si = (i + j) % 2 ? -1.0 : 1.0;
B->d[i][j] = det(A2) * si;
}
}
Mat* C = transpose(B);
freemat(A1);
freemat(A2);
freemat(B);
return C;
}
extern CMat* ctransposeconj(CMat* source)
{
CMat* dest = newcmatnoinit(source->col, source->row);
for (int i = 0; i < dest->row; i++)
for (int j = 0; j < dest->col; j++)
dest->d[i][j] = conju(source->d[j][i]);
return dest;
}
CMat* cadjoint(CMat* A) {
CMat* B = newcmatnoinit(A->row, A->col);
CMat* A1 = newcmatnoinit(A->row - 1, A->col);
CMat* A2 = newcmatnoinit(A->row - 1, A->col - 1);
for (int i = 0; i < A->row; i++) {
cremoverow2(A, A1, i);
for (int j = 0; j < A->col; j++) {
cremovecol2(A1, A2, j);
double si = (i + j) % 2 ? -1.0 : 1.0;
B->d[i][j] = cmultdo( cdet(A2) , si);
}
}
CMat* C = ctranspose(B);
freecmat(A1);
freecmat(A2);
freecmat(B);
return C;
}
Mat* inverse(Mat* A) {
Mat* B = adjoint(A);
double de = det(A);
Mat* C = scalarmultiply(B, 1 / de);
freemat(B);
return C;
}
CMat* cinverse(CMat* A) {
CMat* B = cadjoint(A);
cplx de = cinv(cdet(A));
CMat* C = complexmultiply(B, de);
freecmat(B);
return C;
}
void cinversedest(CMat* A, CMat* dest) {
CMat* B = cadjoint(A);
cplx de = cinv(cdet(A));
complexmultiplydest(B, de, dest);
freecmat(B);
return;
}
Mat* copyvalue(Mat* A) {
Mat* B = newmatnoinit(A->row, A->col);
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
B->d[i][j] = A->d[i][j];
}
}
return B;
}
CMat* copycvalue(CMat* A) {
CMat* B = newcmatnoinit(A->row, A->col);
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
B->d[i][j] = A->d[i][j];
}
}
return B;
}
int copycvaluedest(CMat* A,CMat* dest) {
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
dest->d[i][j] = A->d[i][j];
}
}
return (OK);
}
Mat* triinverse(Mat* A) {
Mat* B = newmatnoinit(A->row, A->col);
for (int i = 0; i < B->row; i++) {
for (int j = i; j < B->col; j++) {
if (i == j) {
B->d[i][j] = 1 / A->d[i][j];
}
else {
B->d[i][j] = -A->d[i][j] / A->d[j][j];
}
}
}
return B;
}
CMat* ctriinverse(CMat* A) {
CMat* B = newcmatnoinit(A->row, A->col);
for (int i = 0; i < B->row; i++) {
for (int j = i; j < B->col; j++) {
if (i == j) {
B->d[i][j] = cinv(A->d[i][j]);
}
else {
B->d[i][j] = cmultdo( cmultco(A->d[i][j], cinv( A->d[j][j])), -1.0);
}
}
}
return B;
}
Mat* rowechelon(Mat* A) {
if (A->row == 1) {
for (int j = 0; j < A->col; j++) {
if (A->d[j] != 0) {
Mat* B = scalarmultiply(A, 1 / A->d[0][j]);
return B;
}
}
Mat* B = newmat(1, A->col, 0);
return B;
}
Mat* B = copyvalue(A);
int ind1 = B->col;
int ind2 = 0;
for (int i = 0; i < B->row; i++) {
for (int j = 0; j < B->col; j++) {
if (B->d[i][j] != 0 && j < ind1) {
ind1 = j;
ind2 = i;
break;
}
}
}//TODOHERE
// Swap columns
if (ind2 > 0) {
for (int j = 0; j < B->col; j++) {
double temp = B->d[0][j];
B->d[0][j] = B->d[ind2][j];
B->d[ind2][j] = temp;
}
}
if (B->d[0][0] != 0) {
double coeff = B->d[0][0];
for (int j = 0; j < B->col; j++) {
B->d[0][j] /= coeff;
}
for (int i = 1; i < B->row; i++) {
coeff = B->d[i][0];
for (int j = 0; j < B->col; j++) {
B->d[i][j] -= coeff * B->d[0][j];
}
}
}
else {
double coeff = 0;
for (int j = 0; j < B->col; j++) {
if (B->d[0][j] != 0 && coeff == 0) {
coeff = B->d[0][j];
B->d[0][j] = 1;
}
else if (B->d[0][j] != 0) {
B->d[0][j] /= coeff;
}
}
}
Mat* B1 = removerow(B, 1);
Mat* B2 = removecol(B1, 1);
Mat* Be = rowechelon(B2);
for (int i = 0, iB=1; i <= Be->row; i++, iB++) {
for (int j = 0, jB=1; j <= Be->col; j++, jB++) {
B->d[iB][jB] = Be->d[i][j];
}
}
freemat(B1);
freemat(B2);
freemat(Be);
return B;
}
CMat* crowechelon(CMat* A) {
if (A->row == 1) {
for (int j = 0; j < A->col; j++) {
if (cmodinv(A->d[0][j]) != 0) {
CMat* B = complexmultiply(A,cinv(A->d[0][j]));
return B;
}
}
CMat* B = newcmat(1, A->col, 0,0);
return B;
}
CMat* B = copycvalue(A);
int ind1 = B->col;
int ind2 = 0;
for (int i = 0; i < B->row; i++) {
for (int j = 0; j < B->col; j++) {
if (!ciszero(B->d[i][j]) && j < ind1) {
ind1 = j;
ind2 = i;
break;
}
}
}
// Swap columns
if (ind2 > 0) {
for (int j = 0; j < B->col; j++) {
cplx temp = B->d[0][j];
B->d[0][j] = B->d[ind2][j];
B->d[ind2][j] = temp;
}
}
if (!ciszero(B->d[0][0])) {
cplx coeff = cinv(B->d[0][0]);
for (int j = 0; j < B->col; j++) {
B->d[0][j] = cmultco(B->d[0][j], coeff);
}
for (int i = 1; i < B->row; i++) {
coeff = B->d[i][0];
for (int j = 0; j < B->col; j++) {
B->d[i][j] = csubco(B->d[i][j], cmultco(B->d[0][j], coeff));
}
}
}
else {
cplx coeff; coeff.re = coeff.im = 0.0;
for (int j = 0; j < B->col; j++) {
if (!ciszero(B->d[0][j]) && ciszero(coeff)) {
coeff = cinv(B->d[0][j]);
B->d[0][j].re = 1; B->d[0][j].im = 0.0;
}
else
B->d[0][j] = cmultco(B->d[0][j], coeff);
}
}
CMat* B1 = cremoverow(B, 0);
CMat* B2 = cremovecol(B1, 0);
CMat* Be = crowechelon(B2);
for (int i = 0, iB = 1; i <= Be->row; i++, iB++) {
for (int j = 0, jB = 1; j <= Be->col; j++, jB++) {
B->d[iB][jB] = Be->d[i][j];
}
}
freecmat(B1);
freecmat(B2);
freecmat(Be);
return B;
}
Mat* hconcat(Mat* A, Mat* B) {
Mat* C = newmatnoinit(A->row, A->col + B->col);
for (int i = 0; i < A->row; i++) {
int k = 0;
for (int j = 0; j < A->col; j++, k++) {
C->d[i][k] = A->d[i][j];
}
for (int j = 0; j < B->col; j++, k++) {
C->d[i][k] = B->d[i][j];
}
}
return C;
}
CMat* chconcat(CMat* A, CMat* B) {
CMat* C = newcmatnoinit(A->row, A->col + B->col);
for (int i = 0; i < A->row; i++) {
int k = 0;
for (int j = 0; j < A->col; j++, k++) {
C->d[i][k] = A->d[i][j];
}
for (int j = 0; j < B->col; j++, k++) {
C->d[i][k] = B->d[i][j];
}
}
return C;
}
Mat* vconcat(Mat* A, Mat* B) {
Mat* C = newmatnoinit(A->row + B->row, A->col);
int k = 0;
for (int i = 0; i < A->row; i++, k++) {
for (int j = 0; j < A->col; j++) {
C->d[k][j] = A->d[i][j];
}
}
for (int i = 0; i < B->row; i++, k++) {
for (int j = 0; j < B->col; j++) {
C->d[k][j] = B->d[i][j];
}
}
return C;
}
CMat* cvconcat(CMat* A, CMat* B) {
CMat* C = newcmatnoinit(A->row + B->row, A->col);
int k = 0;
for (int i = 0; i < A->row; i++, k++) {
for (int j = 0; j < A->col; j++) {
C->d[k][j] = A->d[i][j];
}
}
for (int i = 0; i < B->row; i++, k++) {
for (int j = 0; j < B->col; j++) {
C->d[k][j] = B->d[i][j];
}
}
return C;
}
double norm(Mat* A) {
double d = 0;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
double d0 = A->d[i][j];
d += d0*d0;
}
}
d = sqrt(d);
return d;
}
double cnorm(CMat* A) {
double d = 0;
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
d += cmodinv(A->d[i][j]);
}
}
d = sqrt(d);
return d;
}
Mat* nullmat(Mat* A) {
Mat* RM = rowechelon(A);
int k = RM->row;
for (int i = RM->row-1; i >= 0; i--) {
bool flag = FALSE;
for (int j = 0; j < RM->col; j++) {
if (RM->d[i][j] != 0) {
flag = TRUE;
break;
}
}
if (flag) {
k = i;
break;
}
}
Mat* RRM = submat(RM, 0, k-1, 0, RM->col-1);
freemat(RM);
int nn = RRM->col - RRM->row;
if (nn == 0) {
Mat* N = newmat(0, 0, 0);
return N;
}
Mat* R1 = submat(RRM, 0, RRM->row-1, 0, RRM->row-1);
Mat* R2 = submat(RRM, 0, RRM->row-1, RRM->row, RRM->col-1);
freemat(RRM);
Mat* I = eye(nn);
Mat* T1 = multiply(R2, I);
freemat(R2);
Mat* R3 = scalarmultiply(T1, -1);
freemat(T1);
Mat* T2 = triinverse(R1);
freemat(R1);
Mat* X = multiply(T2, R3);
freemat(T2);
freemat(R3);
Mat* N = vconcat(X, I);
freemat(I);
freemat(X);
for (int j = 0; j < N->col; j++) {
double de = 0;
for (int i = 0; i < N->row; i++) {
de += N->d[i][j] * N->d[i][j];
}
de = sqrt(de);
for (int i = 1; i <= N->row; i++) {
N->d[i][j] /= de;
}
}
return N;
}
MatList* lu(Mat* A) {
if (A->row == 1) {
MatList* ml = (MatList*)tmalloc(sizeof(MatList));
ml->mat = newmat(1, 1, A->d[0][0]);
ml->next = (MatList*)tmalloc(sizeof(MatList));
ml->next->mat = newmat(1, 1, 1);
return ml;
}
double a = A->d[0][0];
double c = 0;
if (a != 0) {
c = 1 / a;
}
Mat* w = submat(A, 0, 0, 1, A->col-1);
Mat* v = submat(A, 1, A->row-1, 0, 0);
Mat* Ab = submat(A, 1, A->row-1, 1, A->col-1);
Mat* T1 = multiply(v, w);
Mat* T2 = scalarmultiply(T1, -c);
Mat* T3 = sum(Ab, T2);
MatList* mlb = lu(T3);
freemat(T1);
freemat(T2);
freemat(T3);
freemat(Ab);
Mat* L = newmat(A->row, A->col, 0);
Mat* U = newmat(A->row, A->col, 0);
for (int i = 0; i < A->row; i++) {
for (int j = 0; j < A->col; j++) {
if (i == 0 && j == 0) {
L->d[i][j] = 1;
U->d[i][j] = a;
}
else if (i == 0 && j > 0) {
U->d[i][j] = w->d[0][j - 1];
}
else if (i > 0 && j == 0) {
L->d[i][j] = c * v->d[0][i - 1];
}
else {
L->d[i][j] = mlb->mat->d[i-1][j-1];
U->d[i][j] = mlb->next->mat->d[i-1][j-1];
}
}
}
MatList* ml = (MatList*)tmalloc(sizeof(MatList));
ml->mat = L;
ml->next = (MatList*)tmalloc(sizeof(MatList));;
ml->next->mat = U;
freemat(w);
freemat(v);
tfree(mlb);
return ml;
}
double innermultiply(Mat* a, Mat* b) {
double d = 0;
int n = a->row;
if (a->col > n) {
n = a->col;
}
for (int i = 0; i <= n; i++) {
d += a->d[0][i] * b->d[0][i];
}
return d;
}
MatList* qr(Mat* A) {
int r = A->row;
int c = A->col;
Mat* Q = newmat(r, r, 0);
Mat* R = newmat(r, c, 0);
Mat* ek = newmat(r, 1, 0);
Mat* uj = newmat(r, 1, 0);
Mat* aj = newmat(r, 1, 0);
for (int j = 0; j < r; j++) {
submat2(A, aj, 0, r-1, j, j);
for (int k = 0; k < r; k++) {
uj->d[0][k] = aj->d[0][k];
}
for (int k = 0; k < j - 1; k++) {
submat2(Q, ek, 0, r-1, k, k);
double proj = innermultiply(aj, ek);
for (int l = 0; l < ek->row; l++) {
ek->d[0][l] *= proj;
}
uj = minus(uj, ek);
}
double nuj = norm(uj);
for (int i = 0; i < r; i++) {
Q->d[i][j] = uj->d[0][i] / nuj;
}
for (int j1 = j-1; j1 < c; j1++) {
R->d[j][j1] = innermultiply(uj, submat(A, 0, r-1, j1, j1)) / nuj;
}
}
MatList* ml = (MatList*)tmalloc(sizeof(MatList));
ml->mat = Q;
ml->next = (MatList*)tmalloc(sizeof(MatList));;
ml->next->mat = R;
freemat(ek);
freemat(uj);
freemat(aj);
return ml;
}