void strassen_mm( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A, const int incRowA, const Dtype *B, const int incRowB, Dtype *C, const int incRowC){ int max_length = maxThree(m, n, k); int new_length = getNumberLargerThanXAndIsPowerOfTwo(max_length); Dtype* newA = pad_matrix(A, m, k, incRowA, new_length, new_length); Dtype* newB = pad_matrix(B, k, n, incRowB, new_length, new_length); Dtype* newC = pad_matrix(C, m, n, incRowC, new_length, new_length); strassen_mm_worker( new_length, new_length, new_length, newA, new_length, newB, new_length, newC, new_length); matrix_copyTo(newC, new_length, new_length, new_length, C, m, n, incRowC); // remove the extra workspace remove_matrix(newA); remove_matrix(newB); remove_matrix(newC); }
ImplicitSystem::~ImplicitSystem () { // Clear data this->clear(); remove_matrix("System Matrix"); }
Dtype* strassen_make_M2_submatrix( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A_2_1, const int incRowA_2_1, const Dtype *A_2_2, const int incRowA_2_2, const Dtype *B_1_1, const int incRowB_1_1){ /* construct M2 by the formula M2 = (A_2_1 + A_2_2) * B_1_1 */ // T1 = A_2_1 + A_2_2 Dtype* T1 = make_matrix(m, k); matrix_addition(m, k, A_2_1, incRowA_2_1, A_2_2, incRowA_2_2, T1, k); Dtype* M2 = make_matrix(m, k); strassen_mm_worker( m, n, k, T1, k, B_1_1, incRowB_1_1, M2, k); remove_matrix(T1); return M2; }
Dtype* strassen_make_M5_submatrix( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A_1_1, const int incRowA_1_1, const Dtype *A_1_2, const int incRowA_1_2, const Dtype *B_2_2, const int incRowB_2_2){ /* construct M5 by the formula M5 = (A_1_1 + A_1_2) * B_2_2 */ // T1 = A_1_1 + A_1_2 Dtype* T1 = make_matrix(m, k); matrix_addition(m, k, A_1_1, incRowA_1_1, A_1_2, incRowA_1_2, T1, k); Dtype* M5 = make_matrix(m, k); strassen_mm_worker( m, n, k, T1, k, B_2_2, incRowB_2_2, M5, k); remove_matrix(T1); return M5; }
Dtype* strassen_make_M4_submatrix( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A_2_2, const int incRowA_2_2, const Dtype *B_2_1, const int incRowB_2_1, const Dtype *B_1_1, const int incRowB_1_1){ /* construct M4 by the formula M4 = A_2_2 * (B_2_1 - B_1_1) */ Dtype* T1 = make_matrix(m, k); // T1 = B_2_1 - B_1_1 matrix_subtraction(m, k, B_2_1, incRowB_2_1, B_1_1, incRowB_1_1, T1, k); Dtype* M4 = make_matrix(m, k); strassen_mm_worker( m, n, k, A_2_2, incRowA_2_2, T1, k, M4, k); remove_matrix(T1); return M4; }
Dtype* strassen_make_M3_submatrix( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A_1_1, const int incRowA_1_1, const Dtype *B_1_2, const int incRowB_1_2, const Dtype *B_2_2, const int incRowB_2_2){ /* construct M3 by the formula M3 = A_1_1 * (B_1_2 - B_2_2) */ // T1 = B_1_2 - B_2_2 Dtype* T1 = make_matrix(m, k); matrix_subtraction(m, k, B_1_2, incRowB_1_2, B_2_2, incRowB_2_2, T1, k); Dtype* M3 = make_matrix(m, k); strassen_mm_worker( m, n, k, A_1_1, incRowA_1_1, T1, k, M3, k); remove_matrix(T1); return M3; }
void Main_win::clear_clicked() { math_->clear(); remove_matrix(); build_matrix(mat_dim_); reset_display(); }
void Main_win::load_clicked() { try { QString q_form = QFileDialog::getOpenFileName(this, tr("Load Matrix")); std::ifstream f; f.open(q_form.toStdString(), std::ios_base::in); if(f.is_open()) { int row = 0; int col = 0; char c = 0; bool flag = true; while(f.get(c)) { if(flag && (c == ' ')) col++; if(c == '\n') { row++; flag = false; } } f.clear(); f.seekg(0, f.beg); std::istream_iterator<double> ii{f}; std::istream_iterator<double> eos{}; std::vector<double> v{ii, eos}; f.close(); remove_matrix(); build_matrix(row, col); mat_dim_.first = row; mat_dim_.second = col; mat_dim_tmp_.first = row; mat_dim_tmp_.second = col; display_matrix(row, col, v); } else throw std::ios_base::failure("cannot open file"); } catch(std::exception& e) { e.what(); to_display(e.what()); } }
void Main_win::set_dim_clicked() { Set_dim dialog_set_dim(this, mat_dim_tmp_); dialog_set_dim.setModal(true); dialog_set_dim.show(); dialog_set_dim.exec(); remove_matrix(); build_matrix(mat_dim_tmp_); mat_dim_ = mat_dim_tmp_; }
// M1 = (A_1_1 + A_2_2) * (B_1_1 + B_2_2) Dtype* strassen_make_M1_submatrix( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A_1_1, const int incRowA_1_1, const Dtype *A_2_2, const int incRowA_2_2, const Dtype *B_1_1, const int incRowB_1_1, const Dtype *B_2_2, const int incRowB_2_2){ /* construct M1 by the formula M1 = (A_1_1 + A_2_2) * (B_1_1 + B_2_2) */ // T1 = (A_1_1 + A_2_2) Dtype* T1 = make_matrix(m, k); matrix_addition(m, k, A_1_1, incRowA_1_1, A_2_2, incRowA_2_2, T1, k); // T2 = (B_1_1 + B_2_2) Dtype* T2 = make_matrix(m, k); matrix_addition(m, k, B_1_1, incRowB_1_1, B_2_2, incRowB_2_2, T2, k); // M1 = T1 * T2 Dtype* M1 = make_matrix(m, k); strassen_mm_worker( m, n, k, T1, k, T2, k, M1, k); remove_matrix(T1); remove_matrix(T2); return M1; }
void Main_win::display_result(const Matrix& m) { remove_matrix(); build_matrix(m.rows(), m.cols()); mat_dim_.first = m.rows(); mat_dim_.second = m.cols(); mat_dim_tmp_.first = m.rows(); mat_dim_tmp_.second = m.cols(); display_matrix(m); }
// M7 = (A_1_2 - A_2_2) * (B_2_1 + B_2_2) Dtype* strassen_make_M7_submatrix( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A_1_2, const int incRowA_1_2, const Dtype *A_2_2, const int incRowA_2_2, const Dtype *B_2_1, const int incRowB_2_1, const Dtype *B_2_2, const int incRowB_2_2){ /* construct M7 by the formula M7 = (A_1_2 - A_2_2) * (B_2_1 + B_2_2) */ Dtype* T1 = make_matrix(m, k); Dtype* T2 = make_matrix(m, k); // T1 = (A_1_2 - A_2_2) matrix_subtraction(m, k, A_1_2, incRowA_1_2, A_2_2, incRowA_2_2, T1, k); // T2 = (B_2_1 + B_2_2) matrix_addition(m, k, B_2_1, incRowB_2_1, B_2_2, incRowB_2_2, T2, k); // M7 = T1 * T2 Dtype* M7 = make_matrix(m, k); strassen_mm_worker( m, n, k, T1, k, T2, k, M7, k); remove_matrix(T1); remove_matrix(T2); return M7; }
/* this script only works for square matrices where the length is a power of 2 */ void strassen_mm_worker( const unsigned int m, const unsigned int n, const unsigned int k, const Dtype *A, const int incRowA, const Dtype *B, const int incRowB, Dtype *C, const int incRowC){ // the matrices must have positive dimension assert(m > 0); assert(n > 0); assert(k > 0); // the matrix must be a square matrix assert(m == n); assert(m == k); /* check if the base case has reached the base condition is defined as when all the dimensions are smaller than 256 */ if(m <= limit_X && n <= limit_X && k <= limit_X){ return matrix_multiplication_base_case( m, n, k, A, incRowA, B, incRowB, C, incRowC); } /* We divide A, B, C into subsections as the following: A = |A_1_1, A_1_2| B = |B_1_1, B_1_2| C = |C_1_1, C_1_2| |A_2_1, A_2_2| |B_2_1, B_2_2| |C_2_1, C_2_2| We first calculate 7 temporary matrices as the follow: M1 = (A_1_1 + A_2_2) * (B_1_1 + B_2_2) M2 = (A_2_1 + A_2_2) * B_1_1 M3 = A_1_1 * (B_1_2 - B_2_2) M4 = A_2_2 * (B_2_1 - B_1_1) M5 = (A_1_1 + A_1_2) * B_2_2 M6 = (A_2_1 - A_1_1) * (B_1_1 + B_1_2) M7 = (A_1_2 - A_2_2) * (B_2_1 + B_2_2) Then, we compute C section by section according to: C_1_1 = M1 + M4 - M5 + M7 C_1_2 = M3 + M5 C_2_1 = M2 + M4 C_2_2 = M1 - M2 + M3 + M6 */ const unsigned int m1 = m / 2; const unsigned int n1 = n / 2; const unsigned int k1 = k / 2; const Dtype* A_1_1 = A; const Dtype* A_1_2 = A_1_1 + k1; const Dtype* A_2_1 = A_1_1 + incRowA*m1; const Dtype* A_2_2 = A_2_1 + k1; Dtype* C_1_1 = C; Dtype* C_1_2 = C_1_1 + n1; Dtype* C_2_1 = C_1_1 + incRowC*m1; Dtype* C_2_2 = C_2_1 + n1; const Dtype* B_1_1 = B; const Dtype* B_1_2 = B_1_1 + n1; const Dtype* B_2_1 = B_1_1 + incRowB*k1; const Dtype* B_2_2 = B_2_1 + n1; /* construct M1 by the formula M1 = (A_1_1 + A_2_2) * (B_1_1 + B_2_2) */ Dtype* M1 = strassen_make_M1_submatrix( m1, n1, k1, A_1_1, incRowA, A_2_2, incRowA, B_1_1, incRowB, B_2_2, incRowB); /* construct M2 by the formula M2 = (A_2_1 + A_2_2) * B_1_1 */ Dtype* M2 = strassen_make_M2_submatrix( m1, n1, k1, A_2_1, incRowA, A_2_2, incRowA, B_1_1, incRowB); /* construct M3 by the formula M3 = A_1_1 * (B_1_2 - B_2_2) */ Dtype* M3 = strassen_make_M3_submatrix( m1, n1, k1, A_1_1, incRowA, B_1_2, incRowB, B_2_2, incRowB); /* construct M4 by the formula M4 = A_2_2 * (B_2_1 - B_1_1) */ Dtype* M4 = strassen_make_M4_submatrix( m1, k1, k1, A_2_2, incRowA, B_2_1, incRowB, B_1_1, incRowB); /* construct M5 by the formula M5 = (A_1_1 + A_1_2) * B_2_2 */ Dtype* M5 = strassen_make_M5_submatrix( m1, n1, k1, A_1_1, incRowA, A_1_2, incRowA, B_2_2, incRowB); /* construct M6 by the formula M6 = (A_2_1 - A_1_1) * (B_1_1 + B_1_2) */ Dtype* M6 = strassen_make_M6_submatrix( m1, n1, k1, A_2_1, incRowA, A_1_1, incRowA, B_1_1, incRowB, B_1_2, incRowB); /* construct M7 by the formula M7 = (A_1_2 - A_2_2) * (B_2_1 + B_2_2) */ Dtype* M7 = strassen_make_M7_submatrix( m1, n1, k1, A_1_2, incRowA, A_2_2, incRowA, B_2_1, incRowB, B_2_2, incRowB); /* compute C_1_1 by the formula C_1_1 = M1 + M4 - M5 + M7 */ strassen_calculate_C_1_1( m1, n1, k1, M1, M4, M5, M7, C_1_1, incRowC); /* compute C_1_2 by the formula C_1_2 = M3 + M5 */ strassen_calculate_C_1_2( m1, n1, k1, M3, M5, C_1_2, incRowC); /* compute C_2_1 by the formula C_2_1 = M2 + M4 */ strassen_calculate_C_2_1( m1, n1, k1, M2, M4, C_2_1, incRowC); /* compute C_2_2 by the formula C_2_2 = M1 - M2 + M3 + M6 */ strassen_calculate_C_2_2( m1, n1, k1, M1, M2, M3, M6, C_2_2, incRowC); /* remove the working space */ remove_matrix(M1); remove_matrix(M2); remove_matrix(M3); remove_matrix(M4); remove_matrix(M5); remove_matrix(M6); remove_matrix(M7); }