This problem is intrinsic to programming and will not disappear
We can only circumvent the problem by making the program invoke different functions when a different type of variable is passed
Vector Jacobi(Matrix P, Matrix Q, Vector b) { Vector v1, v2; int i; float d; for (i = 0; i < 3; i = i + 1) { v1.x[i] = 0; v2.x[i] = 1; } d = 0.1; while ( d > 0.0001 ) { v2 = P*v1 + Q*b; d = distance(v1, v2); v1 = v2; } return(v2); } |
P*v1 (= P.operator*(v1)) Q*b (= Q.operator*(b)) |
must be polymorphic
so that:
Vector sol, b; DenseMatrix P1, Q1; sol = Jacobi(P1, Q1, b); |
will invoke operator* in the DenseMatrix class and
Vector sol, b; SparseMatrix P1, Q1; sol = Jacobi(P1, Q1, b); |
will invoke operator* in the SparseMatrix class
class myOldClass ----> class myNewClass:myOldClass { { virtual function1() virual function1() } } myOldClass X; myNewClass Y; ^ ^ \ / \ / \ / \ / \ / myOldClass *ptr ptr = &X; ptr = &Y; ptr->function1(); ptr->function1(); // Calls function1() // Calls function1() // in myOldClass // in myNewClass |
|
Example:
class DenseMatrix --------------------> { public: float A[3][3]; virtual Vector operator*(Vector &v) { Vector z; int i, j; for (i = 0; i < 3; i=i+1) z.x[i] = 0; for (i = 0; i < 3; i=i+1) for (j = 0; j < 3; j=j+1) z.x[i] = z.x[i] + A[i][j]*v.x[j]; return z; } }; |
class SparseMatrix : DenseMatrix { public: int nnz; float val[6]; int row[6]; int col[6]; virtual Vector operator*(Vector &v) { Vector z; int k; for (k = 0; k < 3; k = k + 1) z.x[k] = 0; for (k = 0; k < nnz; k = k + 1) z.x[row[k]] = z.x[row[k]] + val[k]*v.x[col[k]]; return z; } }; |
Vector Jacobi(DenseMatrix &P, DenseMatrix &Q, Vector b) { Vector v1, v2; int i; float d; for (i = 0; i < 3; i = i + 1) { v1.x[i] = 0; v2.x[i] = 1; } d = 1.0; while ( d > 0.0001 ) { cout << v1.x[0] << "\t" << v1.x[1] << "\t" << v1.x[1] << "\n" ; v2 = P*v1 + Q*b; d = distance(v1, v2); v1 = v2; } return(v2); } |
int main(int argc, char *argv[]) { Vector sol, b; DenseMatrix P1, Q1; sol = Jacobi(P1, Q1, b); // Solves dense system SparseMatrix P2, Q2; sol = Jacobi(P2, Q2, b); // Solves sparse system } |
We must either (1) pass the parameter by reference or (2) use the C style pass address by value.
class Matrix { public: virtual Vector operator*(Vector &v); }; | |
class DenseMatrix:Matrix { public: float A[3][3]; virtual Vector operator*(Vector &v) { Vector z; int i, j; for (i = 0; i < 3; i=i+1) z.x[i] = 0; for (i = 0; i < 3; i=i+1) for (j = 0; j < 3; j=j+1) z.x[i] = z.x[i] + A[i][j]*v.x[j]; return z; } }; |
class SparseMatrix:Matrix { public: int nnz; float val[6]; int row[6]; int col[6]; virtual Vector operator*(Vector &v) { Vector z; int k; for (k = 0; k < 3; k = k + 1) z.x[k] = 0; for (k = 0; k < nnz; k = k + 1) z.x[row[k]] = z.x[row[k]] + val[k]*v.x[col[k]]; return z; } }; |
Vector Jacobi(Matrix & P, Matrix & Q, Vector b) { Vector v1, v2; int i; float d; for (i = 0; i < 3; i = i + 1) { v1.x[i] = 0; v2.x[i] = 1; } d = 1.0; while ( d > 0.0001 ) { cout << v1.x[0] << "\t" << v1.x[1] << "\t" << v1.x[1] << "\n" ; v2 = P*v1 + Q*b; d = distance(v1, v2); v1 = v2; } return(v2); } |
int main(int argc, char *argv[]) { Vector sol, b; DenseMatrix P1, Q1; sol = Jacobi(P1, Q1, b); // Solves dense system SparseMatrix P2, Q2; sol = Jacobi(P2, Q2, b); // Solves sparse system } |