Thread: Cofactor of Matrix, My Assignment Routine Shouldn't But Does Work!

  1. #1
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665

    Cofactor of Matrix, My Assignment Routine Shouldn't But Does Work!

    Hello All,

    I tried writing a cofactoring routine for n x n matrices and my code works but it shouldn't. Like, at all. But it does. Idk how and it's consistent. Can anyone help me understand how it works because I'm amazed that I wrote it, it'll work and yet I swear to God it should not be.

    Basically, my error is when assigning the sub-matrix for the cofactorization method I'm using from here : Mathwords: Cofactor Matrix

    My assignment routine should not work for the sub-matrix because of how I address the rows. under is always 0 and yet it'll assign values to the proper row. Idk how, it's magic.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    long double det(long double **x, int rank) {
    
    
    /* Determinant calculator routine */
    
    
    /* We initialize the resulting determinant to zero */
    
    
       long double result = 0;
    
    
    /* If the rank is two... */
    
    
       if (rank == 2) {
    
    
          return x[0][0]*x[1][1] - x[0][1]*x[1][0];
       }
    
    
    /* Else we begin the recursion */
    
    
       for (int i=0; i<rank; i++) {
    
    
          long double y[rank-1][rank-1];
    
    
          for (int j=1; j<rank; j++) {
    
    
             int c = 0;
    
    
             for (int k=0; k<rank; k++) {
    
    
                if (k == i) continue;
    
    
                y[j-1][c] = x[j][k];
                c++;
             }
          }
    
    
          long double *q[rank-1];
    
    
          for (int t=0; t<rank-1; t++)
             q[t] = y[t];
    
    
          long double **p = q;
    
    
          if (i%2 == 0) result += x[0][i]*det(p, rank-1);
          else result -= x[0][i]*det(p, rank-1);
       }
    
    
    /* Return final determined sum */
    
    
       return result;
    }
    
    
    
    
    long double** cofactor(long double **x, int rank) {
    
    
       //long double y[3][3] = { { 0 } };
    
    
       for (int i=0; i<rank; i++) {
    
    
          for (int j=0; j<rank; j++) {
    
    
             long double z[rank-1][rank-1];
    
    
             int under = 0;
             int oath = 0;
    
    
             for (int a=0; a<rank; a++) {
    
    
                if (a == i) continue;
    
    
                for (int b=0; b<rank; b++) {
    
    
                   if (b == j) continue;
    
    
                   z[under][oath] = x[a][b];
                   oath++;
                }
             }
    
    
             printf("Wtf? (i, j) : (%d, %d) and under is %d\n", i, j, under);
    
    
            long double *try[rank-1];
            for (int lmno=0; lmno<rank-1; lmno++)
                try[lmno] = z[lmno];
    
    
            long double **omfg = try;
    
    
             for (int e=0; e<rank-1; e++) {
    
    
                for (int f=0; f<rank-1; f++) {
           
                   printf(" %.00Lf ", z[e][f]);
                }
    
    
                printf("\n");
             }
    
    
             printf("Determinant is : %Lf\n\n", det(omfg, 2));
    
    
             printf("\n");
          }
       }
    
    
       long double **qq = NULL;
    
    
       return qq;
    }
    
    
    int main(void) {
    
    
       long double x[3][3] = { { 1, 2, 3 }, { 0, 4, 5 }, { 1, 0, 6 } };
    
    
       for (int i=0; i<3; i++) {
    
    
          for (int j=0; j<3; j++) {
           
             printf(" %.00Lf ", x[i][j]);
          }
    
    
          printf("\n");
       }
    
    
       printf("\nThis is then cofactored into...\n\n");
    
    
       long double *z[3];
    
    
       for (int i=0; i<3; i++)
          z[i] = x[i];
    
    
       long double **q = z;
    
    
       long double **p = cofactor(q, 3);
    
    
       return 0;
    }

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Sorry, to help specify, my determinant function, det, is fine. Rather, it's the lines
    Code:
    z[under][oath] = ...

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    It's working because even though you don't change under, you do increment oath every time. That's enough to give you the right element.

    Remember that array indexing is a pointer operation. a[i] means *(a + i). a[i][j] means *(*(a + i) + j)

    So z[under][oath] means *(*(z + under) + oath). If under is always 0, then this becomes *(*z + oath)

  4. #4
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Oh my God. I was literally just thinking that might be why too. Holy crap. Thank you so much, oogabooga.

    Phew.

    Now I can stop nerd raging lol.

    You wouldn't believe it, but calculating the inverse of a matrix is really, really intensive in like every sense of the word.

  5. #5
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Alright, I modified my code to actually behave how I want it but now I keep getting the error : "Address 0x7ff000278 is just below the stack ptr. To suppress, use: --workaround-gcc296-bugs=yes"

    So does that mean there's a bug in gcc or the way valgrind interacts with it? Note that the bug is where it's printing the values in the main-loop. Did I do too many type-casts?

    And here's my updated cofactor method :
    Code:
    long double** cofactor(long double **x, int rank) {
    
    
    /* Cofactorization routine to be used in matrix
       inverse calculation */
    
    
       long double y[rank][rank];
    
    
       for (int i=0; i<rank; i++) {
    
    
          for (int j=0; j<rank; j++) {
    
    
    /* Each respective sub-matrix */
    
    
             long double z[rank-1][rank-1];
    
    
             int under = 0;
    
    
             for (int a=0; a<rank; a++) {
    
    
                if (a == i) continue;
    
    
                int oath = 0;
    
    
                for (int b=0; b<rank; b++) {
    
    
                   if (b == j) continue;
    
    
                   z[under][oath] = x[a][b];
                   oath++;
                } 
    
    
                under++;
             }
    
    
             long double *q[rank-1];
    
    
             for (int m=0; m<rank-1; m++)
                q[m] = z[m];
    
    
             long double **p = q;
    
    
             y[i][j] = det(p, rank-1);
          }
       }
    
    
       long double *q[rank];
    
    
       for (int i=0; i<rank; i++)
          q[i] = y[i];
    
    
       long double **qq = q;
    
    
       return qq;
    }
    
    
    int main(void) {
    
    
       long double x[3][3] = { { 1, 2, 3 }, { 0, 4, 5 }, { 1, 0, 6 } };
    
    
       for (int i=0; i<3; i++) {
    
    
          for (int j=0; j<3; j++) {
           
             printf(" %.00Lf ", x[i][j]);
          }
    
    
          printf("\n");
       }
    
    
       printf("\nThis is then cofactored into...\n\n");
    
    
       long double *z[3];
    
    
       for (int i=0; i<3; i++)
          z[i] = x[i];
    
    
       long double **q = z;
    
    
       long double **p = cofactor(q, 3);
    
    
       for (int i=0; i<3; i++) {
          for (int j=0; j<3; j++) {
             printf(" %Lf ", p[i][j]);
          }
          printf("\n");
       }
    
    
       return 0;
    }

  6. #6
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    You return a pointer that points to a local array. (in function cofactor).


    //Tip: When on error, try thinking again and again if the error is yours, since gcc, etc. are used by many, many people and the chance you (or any of us) find a bug exists, but it is really really small.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  7. #7
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Does that mean that I have to do a malloc and manually copy it back? Omg.

  8. #8
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    If you stick with this approach yes. Cool, it seems to you hard, but once you gain experience, it will be just fine.

    You can check this example, for allocating a 2D array in C.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  9. #9
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Yeah, using manual malloc's works fine. I was just hoping to avoid using malloc at every cost because Idk, I felt like being weird. Hence all the weird type-casts.

    I thought it was because I read here that alloca was safer than malloc. It was alloca that made static allocations, right?

    Oh well. The code works now so I can proceed. Yay!!!

    Thank you everyone for your help. I was nerd raging so hard at this code today, omg.

  10. #10
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I do not know what is alloca :P
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  11. #11
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    alloca is for allocating storage on the stack. It is certainly not "safer" than malloc and is not a replacement for it.

    Probably the easiest solution to your problem is to use one-dimensional arrays to mimic two-d arrays.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef double FLOAT;
    #define FORMAT " %4.0f "
    
    void show(FLOAT *x, int rank) {
       for (int i=0; i<rank; i++) {
          for (int j=0; j<rank; j++)
             printf(FORMAT, x[i * rank + j]);
          printf("\n");
       }
    }
    
    FLOAT det(FLOAT *x, int rank) {
       FLOAT result = 0;
       if (rank == 2)
          return x[0]*x[3] - x[1]*x[2];
       for (int i=0; i<rank; i++) {
          FLOAT y[(rank-1)*(rank-1)];
          for (int j=1; j<rank; j++) {
             for (int k=0; k<rank; k++) {
                if (k == i) continue;
                y[(j-1)*rank+(k-(k>i))] = x[j * rank + k];
             }
          }
          if (i%2 == 0) result += x[i] * det(y, rank-1);
          else result -= x[i]*det(y, rank-1);
       }
       return result;
    }
    
    FLOAT* cofactor(FLOAT *x, int rank) {
       int sign = 1;
       FLOAT *y = malloc(rank * rank * sizeof(*y));
       for (int i=0; i<rank; i++)
          for (int j=0; j<rank; j++) {
             FLOAT z[(rank-1)*(rank-1)];
             for (int a=0; a<rank; a++) {
                if (a == i) continue;
                for (int b=0; b<rank; b++) {
                   if (b == j) continue;
                   z[(a-(a>i))*(rank-1)+(b-(b>j))] = x[a*rank+b];
                }
             }
             y[i * rank + j] = sign * det(z, rank-1);
             sign = -sign;
          }
       return y;
    }
    
    int main(void) {
       FLOAT x[9] = {1, 2, 3,  0, 4, 5,  1, 0, 6};
       show(x, 3);
       printf("cofactor:\n");
       FLOAT *p = cofactor(x, 3);
       show(p, 3);
       return 0;
    }

  12. #12
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    (I know I'm repeating myself here, but I cannot help it! )

    Why not use a structure to describe the matrix?
    Code:
    #ifndef   MATRIX_H
    #define   MATRIX_H
    
    #define  _ISO_C99_SOURCE
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    /* Matrix data owner structure.
     * Many matrices can refer to the same data.
     * The owner is only destroyed when the last matrix
     * referring to the data is destroyed.
    */
    typedef struct {
        size_t   size;
        long     refcount;
        double   data[];    /* C99. Use data[0] if your compiler complains. */
    } owner_t;
    
    /* Matrix data structure.
    */
    typedef struct {
        int      rows;
        int      cols;
        long     rowstep;
        long     colstep;
        double  *origin;
        owner_t *owner;
    } matrix_t;
    
    /* To declare a matrix variable, use either
     *     matrix_t  m = MATRIX_INIT;
     * or
     *     matrix_t  m;
     *     matrix_init(&m);
    */
    #define MATRIX_INIT { 0, 0, 0, 0, NULL, NULL }
    
    static void matrix_init(matrix_t *const mptr)
    {
        if (mptr)
            *mptr = (matrix_t)MATRIX_INIT; /* C99. Assign each member instead if your compiler complains. */
    }
    
    /* Macro referring to a specific element. Ealuates m three times!
    */
    #define MATRIX_ELEMENT(m,row,col) ((m).origin[(row)*(m).rowstep + (col)*(m).colstep])
    
    /* "outside" value returned by matrix_get() and matrix_set,
     * if the specified element is outside the matrix.
    */
    static double matrix_outside = 0.0;
    
    /* Safe matrix element getter.
    */
    static inline double matrix_get(const matrix_t *const mptr, const int row, const int col)
    {
        if (mptr && row >= 0 && col >= 0 && row < mptr->rows && col < mptr->cols)
            return mptr->origin[row * mptr->rowstep + col * mptr->colstep];
        else
            return matrix_outside;
    }
    
    /* Safe matrix element setter.
    */
    static inline double matrix_set(matrix_t *const mptr, const int row, const int col, const double value)
    {
        if (mptr && row >= 0 && col >= 0 && row < mptr->rows && col < mptr->cols)
            return mptr->origin[row * mptr->rowstep + col * mptr->colstep] = value;
        else
            return matrix_outside;
    }
    
    /* Destroy a matrix.
     * Every matrix you create, you must destroy.
     * It is okay to destroy the same matrix twice,
     * and to destroy a matrix that's only init'ed, not created.
     * (Destroying a matrix does not affect related matrices,
     *  even if they refer to the same data.)
    */
    static void matrix_destroy(matrix_t *const mptr)
    {
        if (mptr) {
            if (mptr->owner && --mptr->owner->refcount < 1) {
                mptr->owner->size = 0;
                mptr->owner->refcount = -1073741824L;
                free(mptr->owner);
            }
            *mptr = (matrix_t)MATRIX_INIT; /* C99. Assign each member instead if your compiler complains. */
        }
    }
    
    /* Create a matrix. The elements are non-initialized.
     * Note: If mptr points to an existing matrix, it'll be destroyed first.
     * Returns 0 if successful, errno error code otherwise.
    */
    static int matrix_create(matrix_t *const mptr, const int rows, const int cols)
    {
        const size_t  total = (size_t)rows * (size_t)cols;
        const size_t  bytes = total * sizeof (double);
        const size_t  owned = bytes + sizeof (owner_t);
        owner_t        *owner;
    
        /* Verify sane arguments. */
        if (!mptr || rows < 1 || cols < 1)
            return errno = EINVAL;
    
        /* Destroy existing matrix. */
        matrix_destroy(mptr);
    
        /* Verify the size requested is not too large. */
        if ((size_t)total / (size_t)cols != (size_t)rows ||
            (size_t)bytes / sizeof (double) != total ||
            owned <= bytes)
            return errno = ENOMEM;
    
        /* Allocate the data owner structure. */
        owner = malloc(owned);
        if (!owner)
            return errno = ENOMEM;
    
        /* Owner owns the matrix data, */
        owner->size = total;
        owner->refcount = 1L;
    
        /* and the matrix just refers to it. */
        mptr->owner = owner;
        mptr->origin = owner->data;
    
        mptr->rows = rows;
        mptr->cols = cols;
        /* By default, use row-major order */
        mptr->rowstep = cols;
        mptr->colstep = 1L;
    
        return 0;
    }
    
    /* Transpose a matrix.
     * Returns 0 if successful, errno error code otherwise.
    */
    int matrix_transpose(matrix_t *const mptr)
    {
        if (mptr && mptr->rows > 0 && mptr->cols > 0) {
            const int  old_rows = mptr->rows;
            const int  old_cols = mptr->cols;
            const long old_rowstep = mptr->rowstep;
            const long old_colstep = mptr->colstep;
            mptr->rows = old_cols;
            mptr->cols = old_rows;
            mptr->rowstep = old_colstep;
            mptr->colstep = old_rowstep;
            return 0;
        } else
            return errno = EINVAL;
    }
    
    /* Detach a matrix.
     * If there are views to m, or m itself is a view,
     * this duplicates the data, detaching all views.
     * Returns 0 if successful, errno error code otherwise.
    */
    int matrix_detach(matrix_t *mptr)
    {
        matrix_t temp = MATRIX_INIT;
        int row, col;
    
        /* No matrix specified? */
        if (!mptr || mptr->rows < 1 || mptr->cols < 1)
            return errno = EINVAL;
    
        /* Create a new matrix large enough to hold m. */
        if (matrix_create(&temp, mptr->rows, mptr->cols))
            return errno;
    
        /* Copy matrix contents. */
        for (row = 0; row < temp.rows; row++)
            for (col = 0; col < temp.cols; col++)
                temp.origin[row * temp.rowstep + col * temp.colstep] =
                    mptr->origin[row * mptr->rowstep + col * mptr->colstep];
    
        /* Destroy the old m, */
        matrix_destroy(mptr);
    
        /* replacing it with the new one. */
        *mptr = temp;
    
        return 0;
    }
    
    /* Set matrix d to reflect the contents of matrix m.
     * Any changes in m are visible in d, and vice versa;
     * destroying one does not affect the other.
     * You can transpose one without affecting the other.
     * Returns 0 if success, errno error code otherwise.
    */
    int matrix_attach_all(matrix_t *const dptr, const matrix_t *const mptr)
    {
        if (dptr) {
            matrix_destroy(dptr);
            if (mptr && mptr->origin && mptr->owner->refcount++ > 0) {
                *dptr = *mptr;
                return 0;
            } else
                return errno = ENOENT; /* No matrix to view. */
        } else
            return errno = EINVAL; /* No d matrix specified. */
    }
    
    /* Set matrix d to reflect (partial) contents of matrix m.
     * For example, you can set d to be a single row, column,
     * or even diagonal.
     * Returns 0 if success, errno error code otherwise.
    */
    int matrix_attach(matrix_t *const dptr, const matrix_t *const mptr,
                      const int rows, const int cols,
                      const int origin_row, const int origin_col,
                      const long row_rowstep, const long row_colstep,
                      const long col_rowstep, const long col_colstep)
    {
        int lastrow_row, lastrow_col;
        int lastcol_row, lastcol_col;
    
        /* No d specified? Invalid parameters? */
        if (!dptr || rows < 0 || cols < 0 || origin_row < 0 || origin_col < 0)
            return errno = EINVAL;
    
        matrix_destroy(dptr);
    
        /* No m specified? */
        if (!mptr || !mptr->origin)
            return errno = ENOENT;
    
        /* Origin of view outside m? */
        if (origin_row >= mptr->rows || origin_col >= mptr->cols)
            return errno = EINVAL;
    
        lastrow_row = origin_row + (rows - 1) * row_rowstep;
        lastrow_col = origin_col + (rows - 1) * row_colstep;
    
        lastcol_row = origin_row + (cols - 1) * col_rowstep;
        lastcol_col = origin_col + (cols - 1) * col_colstep;
    
        /* Does the view extend outside m? */
        if (lastrow_row < 0 || lastrow_row >= mptr->rows ||
            lastrow_col < 0 || lastrow_col >= mptr->cols ||
            lastcol_row < 0 || lastcol_row >= mptr->rows ||
            lastcol_col < 0 || lastcol_col >= mptr->cols)
            return errno = EINVAL;
    
        /* d will refer to the same data. */
        if (mptr->owner->refcount++ < 1)
            return errno = ENOENT;
    
        dptr->rows = rows;
        dptr->cols = cols;
        dptr->rowstep = row_rowstep * mptr->rowstep + row_colstep * mptr->colstep;
        dptr->colstep = col_rowstep * mptr->rowstep + col_colstep * mptr->colstep;
        dptr->origin = mptr->origin + origin_row * mptr->rowstep + origin_col * mptr->colstep;
        dptr->owner = mptr->owner;
    
        return 0;
    }
    
    #endif /* MATRIX_H */
    I only use C99-capable compilers, but if you must work with C89/C90, then small changes are needed to make the above compile; they're commented in the code. (The data[0] is a hack, but it's a widely used one; that's why it was standardized later/better.)
    Overall, the matrix representation it uses is much more powerful than the representation used by e.g. GNU Scientific Library.

    While the matrix.h structures do use one extra multiplication per element access (compared to e.g. GSL), the versatility it allows in your algorithm implementation is usually worth it. This was not designed for maximum execution speed, but but maximum versatility and ease of use. (It does not mean it's slow, though; it shouldn't be measurably slower except on very, very large matrices.)

    Typically, I leverage this for submatrices and diagonal vectors. However, any regular pattern from the original matrix that stays within the original matrix is possible -- even something like every third column starting from right, and every second element in each column.

    If you do e.g. linear algebra, and you need matrix views that have extra elements, create a large enough "canvas" matrix first. Create your data matrix as a (centered) view to it. Then, you can create more views that extend past the data area, as long as they stay within the "canvas" matrix.

    Here is a simple example:
    Code:
    #include <stdio.h>
    #include <errno.h>
    #include "matrix.h"
    
    /* Read a matrix from a stream.
     *
     * The format of the input starts with two integers,
     *    ROWS COLS
     * followed by the matrix element in natural order,
     * upper left corner first, followed by the rest of the elements
     * on the top row, followed by the second row, and so on.
     *
     * Returns 0 if success, errno error code otherwise. Special errors:
     *  ENOENT:     No data, end of input.
     *  EDOM:       Invalid number of rows or columns.
     *  EIO:        Error reading matrix elements.
    */
    int matrix_read(matrix_t *const mptr, FILE *const in)
    {
        int    rows, cols, row, col;
    
        /* No m specified? */
        if (!mptr)
            return errno = EINVAL;
    
        matrix_destroy(mptr);
    
        /* No input stream specified? */
        if (!in)
            return errno = EINVAL;
    
        /* Skip leading whitespace. */
        (void)fscanf(in, " ");
    
        /* Read error? End of input? */
        if (ferror(in))
            return errno = EIO;
        if (feof(in))
            return errno = ENOENT;
    
        /* Parse the number of rows and cols. */
        if (fscanf(in, " %d %d", &rows, &cols) != 2)
            return errno = EDOM;
        if (rows < 1 || cols < 1)
            return errno = EDOM;
    
        /* Create a new matrix of desired size. */
        if (matrix_create(mptr, rows, cols))
            return errno;
    
        /* Read loop. */
        for (row = 0; row < rows; row++)
            for (col = 0; col < cols; col++)
                if (fscanf(in , " %lf", &(mptr->origin[row * mptr->rowstep + col * mptr->colstep])) != 1) {
                    matrix_destroy(mptr);
                    return errno = EIO;
                }
    
        /* Success. */
        return 0;
    }
    
    /* Pretty-print a matrix using pattern (for each double).
    */
    void matrix_fprintf(FILE *const out, const char *const pattern, const matrix_t *const mptr)
    {
        int r, c;
    
        for (r = 0; r < mptr->rows; r++) {
            fprintf(out, "[");
            for (c = 0; c < mptr->cols; c++)
                fprintf(out, pattern, mptr->origin[r * mptr->rowstep + c * mptr->colstep]);
            fprintf(out, " ]\n");
        }
    }
    #define matrix_printf(pattern, mptr) matrix_fprintf(stdout, pattern, mptr)
    
    int main(void)
    {
        matrix_t m = MATRIX_INIT;
        matrix_t d = MATRIX_INIT;
        int      n;
    
        /* Read m from standard input. */
        if (matrix_read(&m, stdin)) {
            fprintf(stderr, "Error reading a matrix from standard input.\n");
            return 1;
        }
    
        /* Print the matrix. */
        printf("Read %d-row, %d-column matrix from standard input:\n", m.rows, m.cols);
        matrix_printf(" %5g", &m);
    
        /* Create a column vector of the diagonal elements. */
        if (m.rows <= m.cols)
            n = m.rows;
        else
            n = m.cols;
        if (matrix_attach(&d, &m,
                          1, n,   /* Column vector of n elements */
                          0, 0,   /* Starts at the upper left corner of the matrix */
                          0L, 0L, /* Since there is just one row, the row step is empty */
                          1L, 1L  /* Each vector element is one cell down and right in the matrix */
                         )) {
            fprintf(stderr, "Cannot create a diagonal view.\n");
            return 1;
        }
    
        printf("\nDiagonal elements in the matrix:\n");
        matrix_printf(" %5g", &d);
    
        /* Negate a middle element (of the first row) in the diagonal vector. */
        MATRIX_ELEMENT(d, 0, n/2) *= -1.0;
    
        printf("\nAfter negating the middle element in the diagonal vector:\n");
        matrix_printf(" %5g", &d);
    
        /* We don't need the diagonal vector anymore, so destroy it. */
        matrix_destroy(&d);
        /* Destroying one matrix does not affect the others,
         * even if they refer to the same data. */
    
        printf("\nThe original matrix reflects the change:\n");
        matrix_printf(" %5g", &m);
    
        matrix_destroy(&m);
    
        return 0;
    }
    When running the example, supply it with matrix size (number of rows and columns) and the matrix elements in standard input; for example, if you supply it with
    Code:
    5 5
    11 12 13 14 15
    21 22 23 24 25
    31 32 33 34 35
    41 42 43 44 45
    51 52 53 54 55
    it will output
    Code:
    Read 5-row, 5-column matrix from standard input:
    [    11    12    13    14    15 ]
    [    21    22    23    24    25 ]
    [    31    32    33    34    35 ]
    [    41    42    43    44    45 ]
    [    51    52    53    54    55 ]
    
    Diagonal elements in the matrix:
    [    11    22    33    44    55 ]
    
    After negating the middle element in the diagonal vector:
    [    11    22   -33    44    55 ]
    
    The original matrix reflects the change:
    [    11    12    13    14    15 ]
    [    21    22    23    24    25 ]
    [    31    32   -33    34    35 ]
    [    41    42    43    44    45 ]
    [    51    52    53    54    55 ]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. help I cant get a matrix to work
    By AWOC in forum C Programming
    Replies: 3
    Last Post: 06-08-2010, 08:52 PM
  2. Shouldn't this code work? (select())
    By azjherben in forum Networking/Device Communication
    Replies: 9
    Last Post: 07-20-2009, 04:02 PM
  3. Raw assignment doesn't work!
    By Yarin in forum C++ Programming
    Replies: 7
    Last Post: 09-14-2007, 09:30 AM
  4. values assignment to matrix pointer
    By ronenk in forum C Programming
    Replies: 8
    Last Post: 03-01-2005, 11:30 AM
  5. Shouldn't this code work?
    By DeepFyre in forum C++ Programming
    Replies: 3
    Last Post: 10-03-2004, 01:24 PM