| [aad342c] | 1 | /* FEVS: A Functional Equivalence Verification Suite for High-Performance
|
|---|
| 2 | * Scientific Computing
|
|---|
| 3 | *
|
|---|
| 4 | * Copyright (C) 2004-2010, Stephen F. Siegel, Timothy K. Zirkel,
|
|---|
| 5 | * University of Delaware, University of Massachusetts
|
|---|
| 6 | *
|
|---|
| 7 | * This program is free software; you can redistribute it and/or
|
|---|
| 8 | * modify it under the terms of the GNU General Public License as
|
|---|
| 9 | * published by the Free Software Foundation; either version 3 of the
|
|---|
| 10 | * License, or (at your option) any later version.
|
|---|
| 11 | *
|
|---|
| 12 | * This program is distributed in the hope that it will be useful, but
|
|---|
| 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 15 | * General Public License for more details.
|
|---|
| 16 | *
|
|---|
| 17 | * You should have received a copy of the GNU General Public License
|
|---|
| 18 | * along with this program; if not, write to the Free Software
|
|---|
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|---|
| 20 | * 02110-1301 USA.
|
|---|
| 21 | */
|
|---|
| 22 |
|
|---|
| 23 | /*
|
|---|
| 24 | * Copyright (c) 2004, University of Massachusetts
|
|---|
| 25 | * All Rights Reserved.
|
|---|
| 26 | *
|
|---|
| 27 | * Name: gausselim_seq.c
|
|---|
| 28 | * Date: 21 Jul 2004
|
|---|
| 29 | * Revised: 24 Jul 2004
|
|---|
| 30 | * Author: Anastasia V. Mironova <mironova@laser.cs.umass.edu>
|
|---|
| 31 | * Author: Stephen Siegel <siegel@cs.umass.edu>
|
|---|
| 32 | * Maintainer: Anastasia V. Mironova <mironova@laser.cs.umass.edu>
|
|---|
| 33 | * Reader:
|
|---|
| 34 | *
|
|---|
| 35 | * Compile: cc gausselim_seq.c
|
|---|
| 36 | * Run: a.out n m A[0,0] A[0,1] ... A[n-1,m-1]
|
|---|
| 37 | *
|
|---|
| 38 | * n : number of rows in matrix
|
|---|
| 39 | * m : number of columns in matrix
|
|---|
| 40 | * A[0,0] .. A[n-1,m-1] : entries of matrix (doubles)
|
|---|
| 41 | *
|
|---|
| 42 | * Description: This is a sequential implementation of the
|
|---|
| 43 | * Gauss-Jordan elimination algorithm. The input is an n x m matrix A
|
|---|
| 44 | * of double precision floating point numbers. At termination, A has
|
|---|
| 45 | * been placed in reduced row-echelon form. The original algorithm is
|
|---|
| 46 | * described in many places; see for example Howard Anton, Elementary
|
|---|
| 47 | * Linear Algebra, Wiley, 1977, Section 1.2. In this implementation a
|
|---|
| 48 | * modification to this algorithm has been made to perform backward
|
|---|
| 49 | * subsitution together with the process of reduction to row-echelon
|
|---|
| 50 | * form.
|
|---|
| 51 | *
|
|---|
| 52 | * The entries of the matrix are stored in row-major order, i.e., if
|
|---|
| 53 | * A is the 2x3 matrix
|
|---|
| 54 | *
|
|---|
| 55 | * A[0,0] A[0,1] A[0,2]
|
|---|
| 56 | * A[1,0] A[1,1] A[1,2]
|
|---|
| 57 | *
|
|---|
| 58 | * then its entries are stored as A[0,0], A[0,1], A[0,2], A[1,0],
|
|---|
| 59 | * A[1,1], A[1,2].
|
|---|
| 60 | */
|
|---|
| 61 | #include <stdio.h>
|
|---|
| 62 | #include <string.h>
|
|---|
| 63 | #include <stdlib.h>
|
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 | /* Prints the given matrix of doubles to stdout. The parameter numRows
|
|---|
| 68 | * gives the number of rows in the matrix, and numCols the number of
|
|---|
| 69 | * columns. The string message is printed before the matrix.
|
|---|
| 70 | */
|
|---|
| 71 | void printMatrix(char* message, double* matrix, int numRows, int numCols) {
|
|---|
| 72 | int k;
|
|---|
| 73 |
|
|---|
| 74 | printf("%s",message);
|
|---|
| 75 | for (k = 0; k < numRows*numCols; k++) {
|
|---|
| 76 | printf("%lf ", matrix[k]);
|
|---|
| 77 | if ((k+1)%numCols == 0) {
|
|---|
| 78 | printf("\n");
|
|---|
| 79 | }
|
|---|
| 80 | }
|
|---|
| 81 | printf("\n");
|
|---|
| 82 | }
|
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 | /* Performs Gaussian elimination on the given matrix of doubles. The
|
|---|
| 86 | * parameter numRows gives the number of rows in the matrix, and
|
|---|
| 87 | * numCols the number of columns. Upon return, the matrix will be in
|
|---|
| 88 | * reduced row-echelon form.
|
|---|
| 89 | */
|
|---|
| 90 | void gausselim(double* matrix, int numRows, int numCols, int debug) {
|
|---|
| 91 | int top = 0; // index of current top row
|
|---|
| 92 | int col = 0; // index of current left column
|
|---|
| 93 | int pivotRow = 0; // index of row containing the pivot
|
|---|
| 94 | double pivot = 0.0; // the value of the pivot
|
|---|
| 95 | int i = 0; // loop variable over rows of matrix
|
|---|
| 96 | int j = 0; // loop variable over columns of matrix
|
|---|
| 97 | double tmp = 0.0; // temporary double variable
|
|---|
| 98 |
|
|---|
| 99 | for (top=col=0; top<numRows && col< numCols; top++, col++) {
|
|---|
| 100 |
|
|---|
| 101 | /* At this point we know that the submatarix consisting of the
|
|---|
| 102 | * first top rows of A is in reduced row-echelon form. We will
|
|---|
| 103 | * now consider the submatrix B consisting of the remaining rows.
|
|---|
| 104 | * We know, additionally, that the first col columns of B are all
|
|---|
| 105 | * zero.
|
|---|
| 106 | */
|
|---|
| 107 |
|
|---|
| 108 | if (debug) printf("Top: %d\n\n", top);
|
|---|
| 109 |
|
|---|
| 110 | /* Step 1: Locate the leftmost column of B that does not consist
|
|---|
| 111 | * entirely of zeros, if one exists. The top nonzero entry of
|
|---|
| 112 | * this column is the pivot. */
|
|---|
| 113 |
|
|---|
| 114 | pivot = 0.0;
|
|---|
| 115 | for (; col < numCols; col++) {
|
|---|
| 116 | for (pivotRow = top; pivotRow < numRows; pivotRow++) {
|
|---|
| 117 | pivot = matrix[pivotRow*numCols + col];
|
|---|
| 118 | if (pivot) break;
|
|---|
| 119 | }
|
|---|
| 120 | if (pivot) break;
|
|---|
| 121 | }
|
|---|
| 122 |
|
|---|
| 123 | if (col >= numCols) {
|
|---|
| 124 | break;
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 | /* At this point we are guaranteed that pivot = A[pivotRow,col] is
|
|---|
| 128 | * nonzero. We also know that all the columns of B to the left of
|
|---|
| 129 | * col consist entirely of zeros. */
|
|---|
| 130 |
|
|---|
| 131 | if (debug) {
|
|---|
| 132 | printf("Step 1 result: col=%d, pivotRow=%d, pivot=%lf.\n\n",
|
|---|
| 133 | col, pivotRow, pivot);
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | /* Step 2: Interchange the top row with the pivot row, if
|
|---|
| 137 | * necessary, so that the entry at the top of the column found in
|
|---|
| 138 | * Step 1 is nonzero. */
|
|---|
| 139 |
|
|---|
| 140 | if (pivotRow != top) {
|
|---|
| 141 | for (j = 0; j < numCols; j++) {
|
|---|
| 142 | tmp = matrix[top*numCols + j];
|
|---|
| 143 | matrix[top*numCols + j] = matrix[pivotRow*numCols + j];
|
|---|
| 144 | matrix[pivotRow*numCols + j] = tmp;
|
|---|
| 145 | }
|
|---|
| 146 | }
|
|---|
| 147 |
|
|---|
| 148 | if (debug) {
|
|---|
| 149 | printMatrix("Step 2 result:\n", matrix, numRows, numCols);
|
|---|
| 150 | }
|
|---|
| 151 |
|
|---|
| 152 | /* At this point we are guaranteed that A[top,col] = pivot is
|
|---|
| 153 | * nonzero. Also, we know that (i>=top and j<col) implies
|
|---|
| 154 | * A[i,j] = 0. */
|
|---|
| 155 |
|
|---|
| 156 | /* Step 3: Divide the top row by pivot in order to introduce a
|
|---|
| 157 | * leading 1. */
|
|---|
| 158 |
|
|---|
| 159 | for (j = col; j < numCols; j++) {
|
|---|
| 160 | matrix[top*numCols + j] /= pivot;
|
|---|
| 161 | }
|
|---|
| 162 |
|
|---|
| 163 | if (debug) {
|
|---|
| 164 | printMatrix("Step 3 result:\n", matrix, numRows, numCols);
|
|---|
| 165 | }
|
|---|
| 166 |
|
|---|
| 167 | /* At this point we are guaranteed that A[top,col] is 1.0,
|
|---|
| 168 | * assuming that floating point arithmetic guarantees that a/a
|
|---|
| 169 | * equals 1.0 for any nonzero double a. */
|
|---|
| 170 |
|
|---|
| 171 | /* Step 4: Add suitable multiples of the top row to all other rows
|
|---|
| 172 | * so that all entries above and below the leading 1 become
|
|---|
| 173 | * zero. */
|
|---|
| 174 |
|
|---|
| 175 | for (i = 0; i < numRows; i++) {
|
|---|
| 176 | if (i != top){
|
|---|
| 177 | tmp = matrix[i*numCols + col];
|
|---|
| 178 | for (j = col; j < numCols; j++) {
|
|---|
| 179 | matrix[i*numCols + j] -= matrix[top*numCols + j]*tmp;
|
|---|
| 180 | }
|
|---|
| 181 | }
|
|---|
| 182 | }
|
|---|
| 183 |
|
|---|
| 184 | if (debug) {
|
|---|
| 185 | printMatrix("Step 4 result:\n", matrix, numRows, numCols);
|
|---|
| 186 | }
|
|---|
| 187 | }
|
|---|
| 188 | }
|
|---|
| 189 |
|
|---|
| 190 |
|
|---|
| 191 | /*
|
|---|
| 192 | * Usage: ges [-debug] n m A[0,0] A[0,1] ... A[n-1,m-1]
|
|---|
| 193 | *
|
|---|
| 194 | * n : number of rows in matrix
|
|---|
| 195 | * m : number of columns in matrix
|
|---|
| 196 | * A[0,0] .. A[n-1,m-1] : entries of matrix (doubles)
|
|---|
| 197 | *
|
|---|
| 198 | * Computes reduced row-echelon form and prints intermediate steps.
|
|---|
| 199 | */
|
|---|
| 200 | int main(int argc, char ** argv) {
|
|---|
| 201 | int numRows;
|
|---|
| 202 | int numCols;
|
|---|
| 203 | int k;
|
|---|
| 204 | double* matrix;
|
|---|
| 205 | int debug = 0;
|
|---|
| 206 |
|
|---|
| 207 | if (argc < 3) {
|
|---|
| 208 | printf("Too few arguments.\n");
|
|---|
| 209 | printf("Usage: ges [-debug] n m A[0,0] A[0,1] ... A[n-1,m-1]\n");
|
|---|
| 210 | printf(" n : number of rows in matrix\n");
|
|---|
| 211 | printf(" m : number of columns in matrix\n");
|
|---|
| 212 | printf(" A[0,0] .. A[n-1,m-1] : entries of matrix (doubles)\n");
|
|---|
| 213 | exit(1);
|
|---|
| 214 | }
|
|---|
| 215 | if (!strcmp("-debug", argv[1])) {
|
|---|
| 216 | debug = 1;
|
|---|
| 217 | }
|
|---|
| 218 | sscanf(argv[1+debug], "%d", &numRows);
|
|---|
| 219 | sscanf(argv[2+debug], "%d", &numCols);
|
|---|
| 220 | if (argc != 3 + debug + numRows*numCols) {
|
|---|
| 221 | printf("Incorrect number of matrix entries: %d expected, %d given.\n",
|
|---|
| 222 | numRows*numCols, argc-3-debug);
|
|---|
| 223 | exit(1);
|
|---|
| 224 | }
|
|---|
| 225 | matrix = (double *) malloc(numRows*numCols * sizeof(double));
|
|---|
| 226 | for (k = 0; k < numRows*numCols; k++) {
|
|---|
| 227 | sscanf(argv[k+3+debug], "%lf", &matrix[k]);
|
|---|
| 228 | }
|
|---|
| 229 | printMatrix("Original matrix:\n", matrix, numRows, numCols);
|
|---|
| 230 | gausselim(matrix, numRows, numCols, debug);
|
|---|
| 231 | printMatrix("Reduced row-echelon form:\n", matrix, numRows, numCols);
|
|---|
| 232 | return 0;
|
|---|
| 233 | }
|
|---|