The most useful C-programming snippets on the Internet to help you find your X |
Matrices as vectors in C:
Matrices in C are most times represented as arrays (i.e., vector-like entities) - after all, RAM is a linear thing. It is pretty much straightforward to pack the values of a matrix column-wise or row-wise and map any matrix to a vector. Knowing the dimensions of the initial matrix, it is then easy to access its elements and perform various algebraic operations as we'll see in what follows. The same holds for 3-dimensional and higher dimensional matrices. In what follows, we assume that the matrices are mapped onto arrays column-wise.
Note 1: Here I'm making use of certain types such as size_t and ptrdiff_t. You have to make sure that there are defined on your system. If not, consider replacing them by unsigned long or unsigned short or unsigned int.
Note 2: Here I'm using the notation double a[] because I work with fixed-size arrays. However, exactly the same code will work for dynamically allocated arrays of type double*.
Matrix-Vector Multiplication:
This functions performs the multiplication alpha*a*x+b and updates (adds on) the array y, i.e., it performs the update y += alpha*a*x+b. If b is NULL, it will not be taken into account. It is assumed that all arrays are of compatible dimensions.
void zmvmult(
const double a[],
const double x[],
const double alpha,
const double b[],
const size_t nRows,
const size_t nCols,
double y[]
)
{
ptrdiff_t i, j;
for (i = 0; i < nRows; i++) {
for (j = 0; j < nCols; j++)
ptrdiff_t i, j;
for (i = 0; i < nRows; i++) {
for (j = 0; j < nCols; j++)
y[i] += alpha * a[i + j * nRows] * x[j];
if (b != NULL) y[i] += b[i];
}
}
if (b != NULL) y[i] += b[i];
}
}
Multiply the transpose of a matrix with a vector:
void zmvmult_trans (
const double a[],
const double x[],
const double alpha,
const double b[],
const size_t nRows,
const size_t nCols,
double y[]
)
{
ptrdiff_t i, j;
for (j = 0; j < nCols; j++) {
for (i = 0; i < nRows; i++)
ptrdiff_t i, j;
for (j = 0; j < nCols; j++) {
for (i = 0; i < nRows; i++)
y[j] += alpha * a[i + j * nRows] * x[i];
if (b != 0) y[j] += b[j];
}
}
if (b != 0) y[j] += b[j];
}
}
Solve a linear system whose matrix is lower-triangular:
Consider a system in the form Ly=x, where L is a lower triangular matrix. In this case, the array low_triang contains only the lower-triangular elements of the matrix to avoid redundancy (we don't need to store all those zeros). We assume that the elements of L are packed row-wise, i.e. low_triang = {L(0,0), L(1,0), L(1,1), L(2,0), ...}. It should be simple to modify the code for column-wise packed arrays.
void zlowslv (
const double low_triang[],
double x[],
const size_t n
)
{
ptrdiff_t i, j, offset;
double sum = 0.0;
x[0] = x[0] / low_triang[0];
for (i = 1; i < n; i++) {
offset = ((i + 1) * i) / 2;
sum = x[i];
for (j = 0; j < i; j++) {
sum -= (x[j] * low_triang[offset + j]);
}
x[i] = sum / low_triang[offset + i];
}
}
ptrdiff_t i, j, offset;
double sum = 0.0;
x[0] = x[0] / low_triang[0];
for (i = 1; i < n; i++) {
offset = ((i + 1) * i) / 2;
sum = x[i];
for (j = 0; j < i; j++) {
sum -= (x[j] * low_triang[offset + j]);
}
x[i] = sum / low_triang[offset + i];
}
}
this function solves the system Ly=x and updates the array x with the solution of the system using forward substitution. Notice also that the variable x is not declared to be constant.
Solve a linear system whose matrix is upper-triangular:
Let us now see how we can write a function to solve a system of the form L'y=x. where L is a lower-triangular matrix and L' is its transpose. The following function solves this system using backward substitution and updates x with the solution.
void zlowtrslv(
const double low_triang[],
double x[],
const size_t n
)
{
ptrdiff_t i, j, s;
const size_t size_low = (n * (n + 1)) / 2;
double sum = 0.0;
x[n - 1] = x[n - 1] / low_triang[size_low - 1];
for (i = 1; i < n; i++) {
sum = x[n - i - 1];
s = size_low - i - 1;
for (j = 0; j < i; j++) {
sum -= (low_triang[s] * x[n - 1 - j]);
s -= (n - j - 1);
}
x[n - i - 1] = sum / low_triang[s];
}
}
ptrdiff_t i, j, s;
const size_t size_low = (n * (n + 1)) / 2;
double sum = 0.0;
x[n - 1] = x[n - 1] / low_triang[size_low - 1];
for (i = 1; i < n; i++) {
sum = x[n - i - 1];
s = size_low - i - 1;
for (j = 0; j < i; j++) {
sum -= (low_triang[s] * x[n - 1 - j]);
s -= (n - j - 1);
}
x[n - i - 1] = sum / low_triang[s];
}
}
No comments:
Post a Comment