# Twelvth Week Examples ---   Linear Algebra

Following D. Milicic 2004 Fourteenth Week Examples and 2005 Fourteenth Week Examples.

## Row Operations

The linear system of equations Ax=0 or Ax = b , where A in an m×n matrix, x is an n×1 vector of unknowns and b is an m×1 constant vector can be solved by using the basic equation operations to reduce the equations to an upper triangular system or to an equation for the solution x. These equations can be represented by rows the matrix M=A or by the m×(n+1) augmented matrix matrix, M=(A,b). The three basic row operations are multiplying a row by a constant, swapping two rows or adding the multiple of one row to another.

The first program illustrates row operations. After entering a matrix, the user specifies the row operation and the program performs the desired operation.

```/***********************************************************************************
Treibergs                                                              Mar. 14, 2006

Matrix Manipulator

Enter a matrix. Asks for desired row operation. Then does the operation.

Programming Notes

A type "matrix" is defined to be a structure that holds an array and two integers.
The main program asks for the desired operation, and calls the appropriate subroutine
to execute the operation. There are subroutines to enter the matrix, multiply one of
its rows by a constant, swap rows, add one row to another, and add a multiple of one
row to another.

Since C passes structure arguments "by value", assigning changes to the argument
within the subprogram do not affect the matrices in the calling program unless they
are returned. Therefore, we pass pointers to the structure to the subroutine.
(This is a bit tricky: see section 6.4 of Kernighan and Ritchie.) Thus in main,
"matrix a;" assigns memory to the variable  a  of type "matrix." The declaration
"matrix *a_ptr" assigns space for a single address to the pointer variable  a_ptr,
and then the instruction  "a_ptr = &a"  puts the address of  a  in   a_ptr.

Here is the advantage of passing pointers to the subprogram: pointers are passed
"by reference" so that the structure pointed to by the argument can be altered within
the subprogram. The function prototype is "void mulrom ( matrix *, int, double );"
which tells C that  mulrom  is a subprogram that takes a pointer to the type matrix,
an integer and a double argument and returns no value.

How to get the value of one of the variables in the structure matrix? For example,
the number of columns in the structure pointed at by  a  is "(*a_ptr).c". There is
another notation for this, namely, "a_ptr->c".  Thus if we look inside the subprogram

void
mulrom ( matrix *a_ptr, int i, double c )
{
int j;
i=i-1;
for ( j=0; j < a_ptr->c; j++ )
(a_ptr->m)[i][j] = c * (a_ptr->m)[i][j];
return;
}
a_ptr  is the local name of the pointer to data type matrix and  "a_ptr->m[j][k]"  or
"(a_ptr->m)[j][k]"  is the value of the matrix at  [j][k].

To contrast, look at the Gaussian Elimination program or Milicic's Row Operations
program to see how to pass arguments "by value." That way, you don't need to mess with
pointers and the mathematical logic is generally the same.

matmanip.c
*************************************************************************************/

# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# define  MAXDIM 20

typedef struct
{
double m[MAXDIM][MAXDIM];
int r;
int c;
} matrix;

void
enterm ( matrix * );

void
entm( matrix * );

void
mulrom ( matrix *, int i, double c );

void
addrom ( matrix *, int i, int j );

void
addmurom ( matrix *, int i, double c, int j );

void
swaprom (matrix *, int i, int j );

void
printm ( matrix * );

int
main ( void )
{
double b;
int i=0, icount = 0, j, k, m, m1, m2;
matrix a;
matrix *a_ptr;
a_ptr = &a;

enterm ( a_ptr );
printm ( a_ptr );

while ( icount++ <= 1000 )
{
printf("What would you like to do?   (1.) Multiply a row by a constant?\n"
"                             (2.) Divide a row by a constant?\n"
"                             (3.) Add one row to another?\n"
"                             (4.) Add a multiple of one row to another?\n"
"                             (5.) Swap two rows?\n"
"                             (6.) Enter a new matrix?\n"
"                             (7.) Quit?\n"
"       Enter youir choice:   (");
scanf ( "%d", &i );

switch ( i )
{
case 1:
printf ( "Row i  is multiplied by  c.  Enter  i  c  : ");
scanf ( "%d%lf", &j, &b );
if( ( 1 <=j ) && ( j <= a_ptr->r ) )
{
mulrom ( a_ptr, j, b );
printm ( a_ptr  );
}
else
printf ( "Bad input: Row must be between %d and %d.\n", 1, a_ptr->r );
break;

case 2:
printf ( "Row i  is divided by  c.  Enter  i  c  : ");
scanf ( "%d%lf", &j, &b );
if( b == 0.0 )
printf ( "Bad input: Can't divide by zero.\n" );

else if( ( 1<=j ) && ( j <= a_ptr->r ) )
{
mulrom ( a_ptr, j, 1.0/b );
printm ( a_ptr  );
}
else
printf ( "Bad input: Row must be between %d and %d.\n", 1, a_ptr->r );
break;

case 3:
printf ( "Row i  is replaced by   row i  +  row j.  Enter  i  j  : " );
scanf ( "%d%d", &j, &k );
if ( ( 1 <=j ) && ( j <= a_ptr->r ) && (1 <= k) && ( k <= a_ptr->r ) )
{
addrom ( a_ptr, j, k );
printm ( a_ptr );
}
else
printf ( "Bad input: Both rows must be between %d and %d.\n", 1, a_ptr->r );
break;

case 4:
printf ( "Row i  is replaced by   row i  +  c * row j.  Enter  i  c  j  : ");
scanf ( "%d%lf%d", &j, &b, &k);
if ( ( 1 <=j ) && ( j <= a_ptr->r ) && ( 1 <= k ) && ( k <= a_ptr->c ) )
{
addmurom ( a_ptr , j, b, k );
printm ( a_ptr );
}
else
printf ( "Bad input: Both rows must be between %d and %d.\n", 1, a_ptr->r );
break;

case 5:
printf ( "Row i  and  row j  are swapped.  Enter  i  j  : " );
scanf ( "%d%d", &j, &k );
if ( ( 1 <=j ) && ( j <= a_ptr->r ) && ( 1 <= k ) && ( k <= a_ptr->r ) )
{
swaprom ( a_ptr, j, k );
printm ( a_ptr  );
}
else
printf ( "Bad input: Both rows must be between %d and %d.\n", 1, a_ptr->r );
break;

case 6:
enterm ( a_ptr );
printm ( a_ptr );
break;

case 7:
printf ( "Quit.\n" );
exit ( 0 );
break;

default:
break;
}
}
return EXIT_SUCCESS;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
enterm ( matrix *g_ptr )
{
int i=0, j, k, ir, ic;

while ( i++ <= 10 )
{
printf ( "\nEnter the number of rows and columns  : " );
scanf ( "%d%d", &j, &k );

if ( (1 <=j) && (j <= MAXDIM) && (1 <= k) && (k <= MAXDIM) )
{
for ( ir=0; ir < j; ir++ )
{
for ( ic=0; ic < k; ic++ )
{
printf ( "Enter  a(%d,%d) :", ir+1, ic+1 );
scanf ( "%lf", &g_ptr->m[ir][ic] );
}
}
g_ptr->r = j;
g_ptr->c = k;
return;
}
else
printf ( "Bad input: Both number of rows and number of columns "
"must be between %d and %d.\n", 1, MAXDIM );

}
exit ( 0 );
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
mulrom ( matrix *a_ptr, int i, double c )
{
int j;
i = i  -  1;
for ( j=0; j < a_ptr->c; j++ )
(a_ptr->m)[i][j] = c * (a_ptr->m)[i][j];
return;

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
addrom( matrix *a_ptr, int i, int j )
{
int k;
i = i  -  1;
j = j  -  1;
for ( k=0; k < a_ptr->c; k++ )
(a_ptr->m)[i][k] += (a_ptr->m)[j][k];
return;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
addmurom( matrix *a_ptr, int i, double c,  int j )
{
int k;
i = i  -  1;
j = j  -  1;
for ( k=0; k < a_ptr->c; k++ )
(a_ptr->m)[i][k] += c * (a_ptr->m)[j][k];
return;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
swaprom (matrix *a_ptr, int i, int j)
{
int k;
double temp;
i = i  -  1;
j = j  -  1;
for ( k=0; k < a_ptr->c; k++ )
{
temp = a_ptr->m[i][k];
a_ptr->m[i][k] = a_ptr->m[j][k];
a_ptr->m[j][k] = temp;
}
return;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
printm ( matrix *a_ptr )
{
int i ,j;
printf ( "\n\n" );
for ( i=0; i < a_ptr->r; i++ )
{
for ( j=0; j < a_ptr->c; j++)
printf ( "\t%f", (a_ptr->m)[i][j] );
printf ( "\n\n" );
}
return;
}

```

```/*  Milicic

Elementary Row Transformations

*/
#include  <stdio.h>
#include  <math.h>

#define dim 20

typedef struct {
float coeff[dim][dim];
} matrix; /*define type matrix*/

{
int i, j;
matrix A;

printf("Enter matrix:\n");
for ( i=0 ; i < n ; i++ ) {
printf("\nEnter %d th row >> ",i+1);
for ( j=0 ; j < m ; j++ )
scanf("%f",&A.coeff[i][j]);
}
return(A);
}

/*Function Matdump dumps a matrix to the console */

void Matdump (matrix A, int n, int m)
{
int i, j;

for ( i=0 ; i < n ; i++ ) {
for ( j=0 ; j < m ; j++ )
printf("%f\t",A.coeff[i][j]);
printf("\n");
}
}

matrix Change (matrix A, int n, int m, int i, int j)
{
int k;
float x;

if (i != j) {
for ( k=0 ; k < m ; k++ ) {
x = A.coeff[i][k];
A.coeff[i][k] = A.coeff[j][k];
A.coeff[j][k] = x;
}
}
return(A);
}

/* Function AddRows adds ith row to jth row in the matrix A */

matrix AddRows (matrix A, int n, int m, int i, int j)
{
int k;

for ( k=0 ; k < m ; k++ )
A.coeff[j][k] = A.coeff[j][k] + A.coeff[i][k];
return(A);
}

/* Function MultRow multiplies elements of ith row in the matrix A by mult */

matrix MultRow (matrix A, int n, int m, int i, float mult)
{
int k;

for ( k=0 ; k < m ; k++ )
A.coeff[i][k] = mult * A.coeff[i][k];
return(A);
}

/* Function MultRow multiplies elements of ith row in the matrix A by mult
and adds them to the jth row */

matrix Rowmul (matrix A, int n, int m, int i, int j, float mult)
{
int k;

for ( k=0 ; k < m ; k++ )
A.coeff[j][k] = A.coeff[j][k] + A.coeff[i][k] * mult;
return(A);
}

int main() {
float mult;
matrix A;

printf("Enter  #rows, #columns >> ");
scanf("%d %d",&n, &m);
printf("\n");
printf("\n");
Matdump(A,n,m);
test = 0 ;

do {
printf("\nDo you want to do a row transformation?\n");
printf("1. Switch two rows.\n");
printf("2. Add a row to another row.\n");
printf("3. Multiply a row by a number.\n");
printf("4. Multiply a row by a number and add it to another row.\n");
printf("0. Stop.\n");

case 1:
printf("\nWhich rows to switch? (i,j) >> ");
scanf("%d %d",&i, &j);
A=Change(A, n, m, i-1, j-1);
break;
case 2:
printf("\nAdd ith row to jth row  (i,j) >> ");
scanf("%d %d",&i, &j);
break;
case 3:
printf("\nMultiply ith row with d  (i,d) >> ");
scanf("%d %f",&i, &mult);
A=MultRow(A, n, m, i-1, mult);
break;
case 4:
printf("\nMultiply ith row with d  and add it to jth row (i,j,d) >> ");
scanf("%d %d %f",&i, &j, &mult);
A=Rowmul(A, n, m, i-1, j-1, mult);
break;
default:
test = 1;
}
Matdump(A,n,m);
} while (test != 1);
printf("\n\nQuitting...\n");
}
```

## Gaussian Elimination

The elmentary operations are done systematically to bring the matrix into row-echelon form and into reduced row-echelon form. From these reduced forms, the solutions of the linear system may be read off.

```/***********************************************************************************
Treibergs                                                              Mar. 19, 2006

Gaussian Elimination

Enter a matrix. Finds the row-echelon and reduced-row-echelon form of the matrix.

Programming Notes

A type "matrix" is defined to be a structure that holds a double array and two
integers. The main program asks for matrix input. Then it does Gaussian Elimination
with partial pivoting to find the Echelon Form of the matrix. i.e., of the form

(  0  0  1  *  *  *  *  *  *  *  *  )
(  0  0  0  0  0  0  0  1  *  *  *  )
(  0  0  0  0  0  0  0  0  1  *  *  )
(  0  0  0  0  0  0  0  0  0  0  0  )

where  *  denotes any number. This means that we go column by colums starting at the
leftmost  (j=0) and from the first row  lasti=0. From the jth row from  (lasti=0)
to the last a.r, we find the row  ipivot, that has the largest absolute value.
Then we swap the ipivot and ilast rows. Then we do elimination of all the rows  i
from ilast to a.r  below the pivotal row. This means divide the  ilast  row by
a[ilast][j] then subtract  a[i][j]  times ilast row from the ith row, leaving zeros
below the  [ilast][j]  element.  Swapping in the largest value of the available
elements in the jth  row to the  ilast  row is called partial pivoting. It
guarantees the best numerical performance, reducing the accuracy loss due to taking
the difference of near values which may be exaggerated when divideng by small values.

Finally, we call the routine  "reducem"  to eliminate the entries above the pivotal
elements. Thus the Reduced Row-Echelon form of the above matrix is

(  0  0  1  *  *  *  *  0  0  *  *  )
(  0  0  0  0  0  0  0  1  0  *  *  )
(  0  0  0  0  0  0  0  0  1  *  *  )
(  0  0  0  0  0  0  0  0  0  0  0  )

Reducem  assumes that the incoming matrix is in row-echelon form.

There are subroutines to enter the matrix, multiply one of its rows by a constant,
swap rows and add a multiple of one row to another. Since C passes structure
arguments "by value", the assigned changes to the argument within the subprogram
are made available to the the calling program via  "return."  The alternative is to
pass arguments "by reference.;" see my  MatrixManip  program.

Because of roundoff error, quantities that actually are zero may survive as
infinitessimal quantities. We therefore don't check that a quantity is zero but
rather whether the value is less than  TOL  which we've set to 0.5e-7. We assume
such small quantities are zero, but this may not in fact be true. It would  mess
up calculations on really ill conditioned matrices.

gausselim.c
*************************************************************************************/

# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# define  MAXDIM 20
# define TOL 0.5e-7

typedef struct
{
double m[MAXDIM][MAXDIM];
int r;
int c;
} matrix;

matrix
enterm ( void );

matrix
addmurom ( matrix, int i, double c, int j );

matrix
swaprom (matrix, int i, int j );

matrix
mulrom ( matrix a, int i, double c );

matrix
reducem ( matrix a );

void
printm ( matrix );

int
main ( void )
{
double pivot;
int i, j, k, ipivot, lasti=0, lastj=0;
matrix a;

a = enterm ();
printf("\n\nInitial Matrix");
printm ( a );

for( j=lastj; j < a.c; j++ )
{
ipivot=-1;
pivot=0.0;

/* Partial pivoting step: find the largest in pivotal col below last pivotal row */

for ( i = lasti; i<a.r; i++ )
{
if( fabs ( a.m[i][j] )  > fabs ( pivot ) + TOL )
{
pivot = a.m[i][j];
ipivot = i;
}
}

/* Skip to next col if all zeros. Else swap in pivoti row and eliminate other rows */

if ( ipivot != -1 )
{
if (ipivot != lasti)
a = swaprom ( a, ipivot, lasti);

if ( pivot != 1.0 )
a = mulrom ( a, lasti, 1.0/pivot );

for ( i = lasti  +  1; i < a.r; i++ )
{
if ( fabs ( a.m[i][j] )  <  TOL )
a.m[i][j] = 0.0;
else
a = addmurom ( a, i, -a.m[i][j], lasti );
}
lasti++;
}
}

printf("\nRow-Echelon Form of the Matrix");
printm ( a );

a = reducem ( a );
printf("\nReduced Row-Echelon Form of the Matrix");
printm ( a );

return EXIT_SUCCESS;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
enterm ( void )
{
int i=0, j, k, ir, ic;
matrix g;

while ( i++ <= 10 )
{
printf ( "\nEnter the number of rows and columns  : " );
scanf ( "%d%d", &j, &k );

if ( (1<=j) && (j <= MAXDIM) && (1<= k) && (k <= MAXDIM) )
{
for ( ir=0; ir< j; ir++ )
{
for ( ic = 0; ic < k; ic++ )
{
printf ( "Enter  a(%d,%d) :", ir+1, ic+1 );
scanf ( "%lf", &g.m[ir][ic] );
}
}
g.r = j;
g.c = k;
return g;
}
else
printf ( "Bad input: Both rows must be between %d and %d.\n", 1, MAXDIM );

}
exit ( 0 );
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
mulrom ( matrix a, int i, double c )
{
int j;
for ( j=0; j < a.c; j++ )
a.m[i][j] = c * a.m[i][j];
return a;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
addmurom( matrix a, int i, double c,  int j )
{
int k;
for ( k = 0; k < a.c; k++ )
a.m[i][k] += c * a.m[j][k];
return a;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
swaprom (matrix a, int i, int j)
{
int k;
double temp;
for ( k=0; k < a.c; k++ )
{
temp = a.m[i][k];
a.m[i][k] = a.m[j][k];
a.m[j][k] = temp;
}
return  a;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
printm ( matrix a )
{
int i, j;
printf ( "\n\n" );
for ( i = 0; i < a.r; i++ )
{
for ( j = 0; j < a.c; j++ )
printf ( "\t%f", a.m[i][j] );
printf ( "\n\n" );
}
return;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
reducem ( matrix a )
{
int i, j, ilast = 1, jlast = 1;
if ( a.r > 1)
{
while ( (ilast < a.r) && (jlast < a.c) )
{
if ( fabs ( a.m[ilast][jlast] ) < TOL )
jlast++;
else
{
for ( i=0; i<ilast; i++)
{
if ( fabs(a.m[i][jlast]) > TOL )
{
for ( j = jlast + 1; j<a.c; j++ )
a.m[i][j] -= a.m[i][jlast] * a.m[ilast][j];
}
a.m[i][jlast] = 0.0;
}
ilast++;
jlast++;
}
}
}
return a;
}

```

```/* Milicic

Gauss Elimination

*/
#include <stdio.h>
#include <math.h>

#define true  1
#define false 0

#define dim 20
#define epsilon 0.000001

typedef struct {
float coeff[dim][dim];
} matrix; /*define type matrix*/

{
int i, j;
matrix A;

printf("Enter matrix:\n");
for ( i=0 ; i< n ; i++ ) {
printf("\nEnter %d th row >> ",i+1);
for ( j=0 ; j < m ; j++ )
scanf("%f",&A.coeff[i][j]);
}
return(A);
}

/*Function Matdump dumps a matrix to the console */

void Matdump (matrix A, int n, int m)
{
int i, j;

for ( i=0 ; i < n ; i++ ) {
for ( j=0 ; j < m ; j++ )
printf("%f\t",A.coeff[i][j]);
printf("\n");
}
}
matrix Change (matrix A, int n, int m, int i, int j)
{
int k;
float x;

if (i != j) {
for ( k=0 ; k < m ; k++ ) {
x = A.coeff[i][k];
A.coeff[i][k] = A.coeff[j][k];
A.coeff[j][k] = x;
}
}
return(A);
}

/* Function MultRow multiplies elements of ith row in the matrix A by mult */

matrix MultRow (matrix A, int n, int m, int i, float mult)
{
int k;

for ( k=0 ; k < m ; k++ )
A.coeff[i][k] = mult * A.coeff[i][k];
return(A);
}

/* Function Rowmul multiplies elements of ith row in the matrix A by mult
and adds them to the jth row */

matrix Rowmul (matrix A, int n, int m, int i, int j, float mult)
{
int k;

for ( k=0 ; k < m ; k++ )
A.coeff[j][k] = A.coeff[j][k] + A.coeff[i][k] * mult;
return(A);
}

/* Function Find finds the element of maximal absolute value in
the jth column below the element A (i,j) */

int Find(matrix A, int n, int m, int i, int j)
{
int k,p;

k = i;
for ( p = i+1 ; p < n ; p++ ) {
if (fabs(A.coeff[k][j]) < fabs(A.coeff[p][j]))
k = p;
}
return(k);
}

matrix Gauss (matrix A, int n, int m)
{
int i, j, counter;
int zero;

counter = 0;
for ( j=0 ; j < m ; j++ ) {
zero = true;
for ( i = j - counter ; i < n ; i++ )
if (fabs(A.coeff[i][j]) > epsilon)
zero = false;
if (zero == true)
counter = counter + 1;
else {
i=Find(A, n, m, j - counter,j);
A=Change(A, n, m, i, j - counter);
A=MultRow(A, n, m, j - counter,1 / A.coeff[j - counter][j]);
for ( i = j - counter + 1 ; i < n ; i++ )
if (fabs(A.coeff[i][j]) > epsilon)
A=Rowmul(A, n, m, j - counter, i, -A.coeff[i][j]);
}
}
return(A);
}

/* This procedure reduces a matrix A in row-echelon for to reduced
row-echelon form */

matrix Reduce (matrix A, int n, int m)
{
int i, j, k, zero;

for ( i = n-1 ; i > 0 ; i-- ) {
zero = true;
for ( j = 0 ; j < n ; j++ )
if (fabs(A.coeff[i][j]) > epsilon)
zero = false;
if (zero == false) {
j = 0;
while (fabs(A.coeff[i][j]) < epsilon)
j++;
for ( k = 0 ; k < i ; k++ )
if (fabs(A.coeff[k][j]) > epsilon)
A=Rowmul(A, n, m, i, k, -A.coeff[k][j]);
}
}
return(A);
}

int main() {
int n,m;
matrix A;

printf("Enter  #rows, #columns >> ");
scanf("%d %d",&n, &m);
printf("\n");
printf("\n");
Matdump(A, n, m);
A=Gauss(A, n, m);
printf("\n");
Matdump(A, n, m);
A=Reduce(A, n, m);
printf("\n");
Matdump(A, n, m);
}

```

## Demonstration - - - Multiplying Two Matrices

```/******************************************************
Treibergs                                         5-5-6

Multiplying matrices

Define the matrix structure.
Enter two matrices.
Check if compatible dimensions.
If so, multiply and print the result.

today.c
*******************************************************/

# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# define  MAXDIM 20

typedef struct
{
double m[MAXDIM][MAXDIM];
int r;
int c;
}
matrix;

matrix
enterm ( void );

matrix
mulm ( matrix, matrix );

void
printm ( matrix );

int
main ( void )
{
matrix a, b, c;

printf("First matrix:\n");
a=enterm();

printf("\n\nSecond matrix:\n");
b=enterm();

c = mulm(a,b);

printf("\n\nFirst matrix:");
printm(a);

printf("\nSecond matrix:");
printm(b);

printf("\nProduct of the two matrices:");
printm(c);

return EXIT_SUCCESS;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
enterm ( void )
{
int i=0, j, k, ir, ic;
matrix g;

while ( i++ <= 10 )
{
printf ( "\nEnter the number of rows and columns  : " );
scanf ( "%d%d", &j, &k );

if ( (1<=j) && (j <= MAXDIM) && (1<= k) && (k <= MAXDIM) )
{
for ( ir=0; ir< j; ir++ )
{
printf ( "Enter row  a(%d,*) :", ir+1 );
for ( ic = 0; ic < k; ic++ )
scanf ( "%lf", &g.m[ir][ic] );
}
g.r = j;
g.c = k;
return g;
}
else
printf ( "Bad input: Both number of rows and number of columns must be between %d and %d.\n", 1, MAXDIM );

}
exit ( 0 );
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

matrix
mulm ( matrix a, matrix b )
{
double s;
int i,j,k;
matrix c;

if( a.c != b.r )
{
printf("Error--incompatible dimensions: the number of columns of the first matrix must\n"
"                                equal the number of rows of the second matrix.\n");
exit(0);
}
else
{
c.r=a.r;
c.c=b.c;
for( i=0; i<a.r; i++)
for(j=0; j<b.c; j++)
{
s=0.0;
for(k=0; k<b.r; k++)
s += a.m[i][k]*b.m[k][j];
c.m[i][j]=s;
}
}
return c;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void
printm ( matrix a )
{
int i, j;
printf ( "\n\n" );
for ( i = 0; i < a.r; i++ )
{
for ( j = 0; j < a.c; j++ )
printf ( "\t%f", a.m[i][j] );
printf ( "\n\n" );
}
return;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

```