void dcmatrix_Multiply ( int n, int m, int l, dcmplx a[n][m], POLY b[m][l], POLY c[n][l] ) { int i, j, k; POLY tmp1, tmp2; zero_matrix ( n, l, c); for ( i=0; i<n; i++ ) { for ( j=0; j<l; j++ ) { for ( k=0; k<m; k++ ) { tmp1 = mul_dcmplx_poly ( a[i][k], b[k][j] ); tmp2.p=add_poly(c[i][j].d, c[i][j].p, tmp1.d, tmp1.p, &(tmp2.d)); free(c[i][j].p); c[i][j]=assign_poly(tmp2); free(tmp1.p); free(tmp2.p); /* c[i][j]+=a[i][k]*b[k][j];*/ } } } }
// Helper function to multiply two matrices smartly void strassen_mult(MATRIX* mOrig1, MATRIX* mOrig2, MATRIX* res) { // Preprocess original matrices for multiplication MATRIX* m1 = malloc(sizeof(MATRIX)); MATRIX* m2 = malloc(sizeof(MATRIX)); strassen_preprocess(mOrig1,mOrig2,m1,m2); if(m1 == NULL || m2 == NULL) return; MATRIX* m3 = malloc(sizeof(MATRIX)); zero_matrix(m1->numRows, m2->numCols, m3); strassen_helper(m1, m2, m3); // Grab original dimensions. int origNumRows = mOrig1->numRows; int origNumCols = mOrig2->numCols; // Strip final result matrix. strassen_postprocess(m3, res, origNumRows, origNumCols); // Free memory free_matrix(m1); free_matrix(m2); free_matrix(m3); }
// (*element_function)() defines each element of the new matrix, // and may depend on the values of i, j, n, and m // int n,m are the desired width,height dimensions and must be >= 1 // int x,y are the row,column offsets for computing a sub-matrix // x,y must be >=1 matrix new_matrix(float (*element_function)(int, int, int, int), int n, int m, int x, int y) { matrix mat; int i,j; if((mat = zero_matrix(n,m)) == NULL) { return NULL; } if(x < 1 || y < 1) { fprintf(stderr,"Error: offset out of bounds\n"); return NULL; } // set offsets, they are 1 after allocation // width and height were set during allocation mat->x_offset = x; mat->y_offset = y; // element-wise matrix definition loop for (i = x; i < n+x; i++) { for(j = y; j < m+y; j++) { mat->A[i-x][j-y] = (*element_function)(i,j,n,m); } } return mat; }
Matrix make_identity(){ Matrix matrix = make_matrix(); zero_matrix(matrix); for(int i=0; i<4; i++){ matrix[i][i] = 1; } return matrix; }
/** * NAME: strassen_postprocess * INPUT: MATRIX* mOrig, MATRIX* mNew2, int colSize, int rowSize * USAGE: Strips zeros from mOrig and outputs a new rowSize by colSize matrix. * * NOTES: Assumes all inputs are already initialized. */ void strassen_postprocess(MATRIX* mOrig, MATRIX* mNew, int colSize, int rowSize) { // Allocate memory for the new matrix and strip zeros zero_matrix(rowSize, colSize, mNew); for(int i = 0; i < rowSize; i++) { // Goes across the columns of m2 for (int j=0; j< colSize; j++) // Grab entries from original matrix. mNew->matrix[i][j] = mOrig->matrix[i][j]; } }
MutableMatrix *MutableMatrix::from_matrix(const Matrix *m, bool prefer_dense) { MutableMatrix *result = zero_matrix(m->get_ring(), m->n_rows(), m->n_cols(), prefer_dense); Matrix::iterator i(m); for (unsigned int c=0; c<m->n_cols(); c++) { for (i.set(c); i.valid(); i.next()) result->set_entry(i.row(), c, i.entry()); } return result; }
int main() { std::vector<std::vector<int>> matrix; for(auto i = 0 ; i < 4; ++i){ matrix.push_back(std::vector<int>()); for (auto j = 0; j < 4; ++j) { matrix[i].push_back(j+i); } } zero_matrix(matrix); for(auto i = 0 ; i < 4; ++i){ for (auto j = 0; j < 4; ++j) { std::cout << matrix[i][j]; } std::cout << std::endl; } }
// This may be useful for something matrix identity_matrix(int n) { matrix I; int j; if((I = zero_matrix(n,n)) == NULL) { return NULL; } for(j = 0; j < n; j++) { I->A[j][j] = 1.; } return I; }
void Call_Hermite ( int n, int m ) { POLY a[n][m], a1[n][m]; POLY p[n][n], t[n][m]; dcmplx deter, dcmplx_p[n][n], x; int k; printf("1 random matrix.\n"); printf("2 input your own matrix.\n"); printf("Please choose the test matrix:"); scanf("%d", &k ); printf("%d\n\n", k ); if(k==1) random_matrix ( n, m, a); if(k==2) read_matrix( n, m, a ); printf("the original matrix generated :\n"); print(n,m,a); zero_matrix ( n, m, a1); I_matrix ( n, p); copy ( n, m, a, t); /* Eliminate_Col(n,m,a,p,0,0); */ /* Eliminate_Row(n,m,a,q,0,0); */ Hermite(n, m, a, p); printf("The hermite form of matrix a is :\n"); print(n,m,a); /* now begin to test the result */ Multiply ( n, n, m, p, t, a1 ); printf("The calculated hermite form with p*a is:\n"); print(n, m, a1); printf(" p is:\n"); print(n, n, p); x=create1(1.1); evaluate_matrix(n, n, p, dcmplx_p, x); deter=determinant(n, dcmplx_p); printf("The determinant of the p is: "); writeln_dcmplx(deter); }
/** * NAME: pad_matrix * INPUT: MATRIX* mOrig, MARIX* mNew * USAGE: Converts a matrix to the smallest 2^n by 2^n square matrix. * Pads missing values with 0. Stores the result in mNew. * Original Input is unmodified. * * NOTES: Assumes mOrig and mNew are already initalized. */ void pad_matrix(MATRIX* mOrig, MATRIX* mNew) { // Calculate the new dimensions. int origDims; if(mOrig->numRows > mOrig->numCols) origDims = mOrig->numRows; else origDims = mOrig->numCols; int newDims = next_power(origDims); // Allocate memory for the new matrix and add zeros. zero_matrix(newDims, newDims, mNew); for(int i = 0; i < newDims; i++) { for (int j=0; j< newDims; j++) // Grab entries if they are in the original matrix. // Otherwise, pad with 0. if(i < mOrig->numRows && j < mOrig->numCols) mNew->matrix[i][j] = mOrig->matrix[i][j]; } }
// Return matrix C = AB matrix mult_matrix(matrix A, matrix B) { matrix C; unsigned int i,j,k; float sum; // Make sure we can multiply these matrices if(A->m != B->n) { fprintf(stderr,"Matrices are dimensionally incompatible."); return NULL; } // Set up space for our matrix product if((C = zero_matrix(A->n, B->m)) == NULL) { return NULL; } // Set offsets for sub-matrix C C->x_offset = A->x_offset; C->y_offset = B->y_offset; // This is the O(k*n*m) algorithm for matrix multiplication for(i = 0; i < A->n; i++) { for(j = 0; j < B->m; j++) { sum = 0.; for(k = 0; k < A->n; k++) { sum += A->A[i][k] * B->A[k][j]; } C->A[i][j] = sum; } } return C; }
/** * NAME: strassen_postprocess * INPUT: MATRIX* mOrig, MATRIX* mNew2, int colSize, int rowSize * USAGE: Strips zeros from mOrig and outputs a new rowSize by colSize matrix. * * NOTES: Assumes all inputs are already initialized. */ void strassen_helper(MATRIX* m1, MATRIX* m2, MATRIX* res) { // base case if (m1->numRows <= 1) { mult_bignums(&m1->matrix[0][0], &m2->matrix[0][0], &res->matrix[0][0]); } else { // split mOrig1 & mOrig2 into a 2x2 of submatrices int n = m1->numRows/2; // Initialize submatrices MATRIX* a11 = malloc(sizeof(MATRIX)); MATRIX* a12 = malloc(sizeof(MATRIX)); MATRIX* a21 = malloc(sizeof(MATRIX)); MATRIX* a22 = malloc(sizeof(MATRIX)); MATRIX* b11 = malloc(sizeof(MATRIX)); MATRIX* b12 = malloc(sizeof(MATRIX)); MATRIX* b21 = malloc(sizeof(MATRIX)); MATRIX* b22 = malloc(sizeof(MATRIX)); zero_matrix(n,n,a11); zero_matrix(n,n,a12); zero_matrix(n,n,a21); zero_matrix(n,n,a22); zero_matrix(n,n,b11); zero_matrix(n,n,b12); zero_matrix(n,n,b21); zero_matrix(n,n,b22); // Strassens algorithm for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { // First matrix a11->matrix[i][j] = m1->matrix[i][j]; a12->matrix[i][j] = m1->matrix[i][j+n]; a21->matrix[i][j] = m1->matrix[i+n][j]; a22->matrix[i][j] = m1->matrix[i+n][j+n]; // Second matrix b11->matrix[i][j] = m2->matrix[i][j]; b12->matrix[i][j] = m2->matrix[i][j+n]; b21->matrix[i][j] = m2->matrix[i+n][j]; b22->matrix[i][j] = m2->matrix[i+n][j+n]; } } // Create two temporary matrices MATRIX* temp1 = malloc(sizeof(MATRIX)); MATRIX* temp2 = malloc(sizeof(MATRIX)); zero_matrix(n,n,temp1); zero_matrix(n,n,temp2); // The 7 important variable matrices of Strassens algorithm MATRIX* x1 = malloc(sizeof(MATRIX)); MATRIX* x2 = malloc(sizeof(MATRIX)); MATRIX* x3 = malloc(sizeof(MATRIX)); MATRIX* x4 = malloc(sizeof(MATRIX)); MATRIX* x5 = malloc(sizeof(MATRIX)); MATRIX* x6 = malloc(sizeof(MATRIX)); MATRIX* x7 = malloc(sizeof(MATRIX)); zero_matrix(n,n,x1); zero_matrix(n,n,x2); zero_matrix(n,n,x3); zero_matrix(n,n,x4); zero_matrix(n,n,x5); zero_matrix(n,n,x6); zero_matrix(n,n,x7); // Fill those 7 matrices with the correct values add_matrices(a11, a22, temp1); add_matrices(b11, b22, temp2); strassen_helper(temp1, temp2, x1); add_matrices(a21, a22, temp1); strassen_helper(temp1, b11, x2); subtract_matrices(b12, b22, temp2); strassen_helper(a11, temp2, x3); subtract_matrices(b21, b11, temp2); strassen_helper(a22, temp2, x4); add_matrices(a11, a12, temp1); strassen_helper(temp1, b22, x5); subtract_matrices(a21, a11, temp1); add_matrices(b11, b12, temp2); strassen_helper(temp1, temp2, x6); subtract_matrices(a12, a22, temp1); add_matrices(b21, b22, temp2); strassen_helper(temp1, temp2, x7); // 4 temporary result submatrices MATRIX* res11 = malloc(sizeof(MATRIX)); MATRIX* res12 = malloc(sizeof(MATRIX)); MATRIX* res21 = malloc(sizeof(MATRIX)); MATRIX* res22 = malloc(sizeof(MATRIX)); zero_matrix(n, n, res11); zero_matrix(n, n, res12); zero_matrix(n, n, res21); zero_matrix(n, n, res22); add_matrices(x3, x5, res12); add_matrices(x2, x4, res21); add_matrices(x1, x4, temp1); add_matrices(temp1, x7, temp2); subtract_matrices(temp2, x5, res11); add_matrices(x1, x3, temp1); add_matrices(temp1, x6, temp2); subtract_matrices(temp2, x2, res22); // Group submatrices for (int i=0; i<n; i++) { for (int j=0; j<n; j++) { // first matrix res->matrix[i][j] = res11->matrix[i][j]; res->matrix[i][j+n] = res12->matrix[i][j]; res->matrix[i+n][j] = res21->matrix[i][j]; res->matrix[i+n][j+n] = res22->matrix[i][j]; } } // Free all matrices. free_matrix(a11); free_matrix(a12); free_matrix(a21); free_matrix(a22); free_matrix(b11); free_matrix(b12); free_matrix(b21); free_matrix(b22); free_matrix(temp1); free_matrix(temp2); free_matrix(x1); free_matrix(x2); free_matrix(x3); free_matrix(x4); free_matrix(x5); free_matrix(x6); free_matrix(x7); free_matrix(res11); free_matrix(res12); free_matrix(res21); free_matrix(res22); } }
// Load a matrix from a file matrix load_matrix(const char *filename) { matrix mat,mat_info; FILE *infile; unsigned int i,j,b; struct stat if_stat; b = 0; // Attempt to open file for reading if ((infile = fopen(filename, "r+")) == NULL) { perror("Error opening file"); return NULL; } // Read in the dimensions of the old matrix first // and then allocate space for where the rest of it goes if ((mat_info = zero_matrix(1,1)) == NULL) // Only for dimensions { return NULL; } b = sizeof(*mat_info)*fread(mat_info,sizeof(*mat_info),1,infile); // At this point, we should check to make sure the dimensions specified // in the file match the size of the rest of the file. If not, it's very // likely that someone has modified them with intent to corrupt the heap stat(filename,&if_stat); if ((if_stat.st_size - sizeof(*mat_info)-1) != (sizeof(mat_info->A)*mat_info->n*mat_info->m)) { // If we don't catch this here and dimensions are wrong, fread() // will experience errors later trying to read parts of the file // that don't exist fprintf(stderr,"Error: Matrix file has inconsistent dimensions\n"); return NULL; } // This is where our matrix will go if ((mat = zero_matrix(mat_info->n,mat_info->m)) == NULL) { return NULL; } // Set offsets mat->x_offset = mat_info->x_offset; mat->y_offset = mat_info->y_offset; // Read in each value of the matrix for (i = 0; i < mat->n; i++) { for(j = 0; j < mat->m; j++) { b += sizeof(mat->A)*fread( &mat->A[i][j], sizeof(mat->A), 1, infile); } } // Check the number of bytes read against the number we expect // if perror() returns "Success" here, it's very likely that someone // has modified the matrix file with intent to corrupt the heap if (b != (sizeof(*mat)+(sizeof(mat->A)*mat->n*mat->m))) { perror("Error reading file"); return NULL; } fclose(infile); //printf("Read %d bytes from %s\n",b,filename); return mat; }
// Make a zero matrix, using the same ring and density taken from 'mat'. MutableMat* makeZeroMatrix(size_t nrows, size_t ncols) const { return zero_matrix(mat.get_ring(), &mat.ring(), nrows, ncols); }