The following program first obtains the conventional matrix product of two ordinary matrices (con_matrix<double>). After that, it constructs equivalent block matrices (var_matrix<var_matrix<double>>) and multiples those, obtaining the equivalent product.
#include "SOME_DIRECTORY/mat_gen_dim.h"
using namespace mat_gen_dim;
// the following will always be the initialization of "which" for conventional matrix multiplication
vec_bool const which {false,true,true,false};
struct mul_dou {
double operator() (double const x, double const y) { return x * y; }
};
struct add_asgn_dou {
double operator() (double & x, double const y) { return x += y; }
};
struct mul_mat_dou {
var_matrix<double> operator() (
con_matrix<double> const & x,
con_matrix<double> const & y)
{
return inner_product<mul_dou, add_asgn_dou> (x, y, which);
}
};
struct add_asgn_mat_dou {
var_matrix<double> operator() (
var_matrix<double> & x,
con_matrix<double> const & y)
{
return x += y;
}
};
int main () {
cout.setf (std::ios::fixed, std::ios::floatfield);
cout.precision (4);
// you can change these numbers:
sign_int const A (3); // non-negative
sign_int const B (5); // non-negative
sign_int const C (6); // positive
sign_int const D (4); // positive
sign_int const E (2); // non-negative
sign_int const F (1); // non-negative
form const f_AB_CD { blt (0, A + B), blt (0, C + D) };
form const f_A_C { blt (0, A ), blt (0, C ) };
form const f_A_D { blt (0, A ), blt (C, C + D) };
form const f_B_C { blt (A, A + B), blt (0, C ) };
form const f_B_D { blt (A, A + B), blt (C, C + D) };
form const f_CD_EF { blt (0, C + D), blt (0, E + F) };
form const f_C_E { blt (0, C ), blt (0, E ) };
form const f_C_F { blt (0, C ), blt (E, E + F) };
form const f_D_E { blt (C, C + D), blt (0, E ) };
form const f_D_F { blt (C, C + D), blt (E, E + F) };
cout << "\n\n the unblocked matrix: ";
con_matrix<double> m_AB_CD {sub_matrix_linear<double> (f_AB_CD,1.0)};
con_matrix<double> m_CD_EF {sub_matrix_linear<double> (f_CD_EF,2.0)};
con_matrix<double> m_AB_EF {inner_product
<mul_dou, add_asgn_dou> (m_AB_CD, m_CD_EF, which)};
cout << "\n m_AB_CD: " << m_AB_CD;
cout << "\n m_CD_EF: " << m_CD_EF;
cout << "\n m_AB_EF: " << m_AB_EF;
cout << "\n\n extraction of blocks: ";
con_matrix<double> m_A_C (con_lens_less_range<double> (m_AB_CD, f_A_C));
con_matrix<double> m_A_D (con_lens_less_range<double> (m_AB_CD, f_A_D));
con_matrix<double> m_B_C (con_lens_less_range<double> (m_AB_CD, f_B_C));
con_matrix<double> m_B_D (con_lens_less_range<double> (m_AB_CD, f_B_D));
cout << "\n m_A_C: " << m_A_C;
cout << "\n m_A_D: " << m_A_D;
cout << "\n m_B_C: " << m_B_C;
cout << "\n m_B_D: " << m_B_D;
con_matrix<double> m_C_E (con_lens_less_range<double> (m_CD_EF, f_C_E));
con_matrix<double> m_C_F (con_lens_less_range<double> (m_CD_EF, f_C_F));
con_matrix<double> m_D_E (con_lens_less_range<double> (m_CD_EF, f_D_E));
con_matrix<double> m_D_F (con_lens_less_range<double> (m_CD_EF, f_D_F));
cout << "\n m_C_E: " << m_C_E;
cout << "\n m_C_F: " << m_C_F;
cout << "\n m_D_E: " << m_D_E;
cout << "\n m_D_F: " << m_D_F;
cout << "\n\n assembly of blocks into compound matrix: ";
form const f_22 { blt (0, 2), blt (0, 2) };
var_matrix<var_matrix<double>> m_m_AB_CD (f_22, {m_A_C, m_A_D, m_B_C, m_B_D});
var_matrix<var_matrix<double>> m_m_CD_EF (f_22, {m_C_E, m_C_F, m_D_E, m_D_F});
var_matrix<var_matrix<double>> m_m_AB_EF {inner_product
<mul_mat_dou, add_asgn_mat_dou> (m_m_AB_CD, m_m_CD_EF, which)};
cout << "\n m_m_AB_CD: " << m_m_AB_CD;
cout << "\n m_m_CD_EF: " << m_m_CD_EF;
cout << "\n m_m_AB_EF: " << m_m_AB_EF;
return 0;
}
Here is a small portion of the output:
m_AB_EF:
( 0 0 ) = { 25.6850 } ( 0 1 ) = { 25.7895 } ( 0 2 ) = { 25.8940 }
( 1 0 ) = { 28.1350 } ( 1 1 ) = { 28.2495 } ( 1 2 ) = { 28.3640 }
( 2 0 ) = { 30.5850 } ( 2 1 ) = { 30.7095 } ( 2 2 ) = { 30.8340 }
( 3 0 ) = { 33.0350 } ( 3 1 ) = { 33.1695 } ( 3 2 ) = { 33.3040 }
( 4 0 ) = { 35.4850 } ( 4 1 ) = { 35.6295 } ( 4 2 ) = { 35.7740 }
( 5 0 ) = { 37.9350 } ( 5 1 ) = { 38.0895 } ( 5 2 ) = { 38.2440 }
( 6 0 ) = { 40.3850 } ( 6 1 ) = { 40.5495 } ( 6 2 ) = { 40.7140 }
( 7 0 ) = { 42.8350 } ( 7 1 ) = { 43.0095 } ( 7 2 ) = { 43.1840 }
m_m_AB_EF:
( 0 0 ) = {
( 0 0 ) = { 25.6850 } ( 0 1 ) = { 25.7895 }
( 1 0 ) = { 28.1350 } ( 1 1 ) = { 28.2495 }
( 2 0 ) = { 30.5850 } ( 2 1 ) = { 30.7095 }
}
( 0 1 ) = {
( 0 2 ) = { 25.8940 }
( 1 2 ) = { 28.3640 }
( 2 2 ) = { 30.8340 }
}
( 1 0 ) = {
( 3 0 ) = { 33.0350 } ( 3 1 ) = { 33.1695 }
( 4 0 ) = { 35.4850 } ( 4 1 ) = { 35.6295 }
( 5 0 ) = { 37.9350 } ( 5 1 ) = { 38.0895 }
( 6 0 ) = { 40.3850 } ( 6 1 ) = { 40.5495 }
( 7 0 ) = { 42.8350 } ( 7 1 ) = { 43.0095 }
}
( 1 1 ) = {
( 3 2 ) = { 33.3040 }
( 4 2 ) = { 35.7740 }
( 5 2 ) = { 38.2440 }
( 6 2 ) = { 40.7140 }
( 7 2 ) = { 43.1840 }
}