mat_gen_dim section 8D.
home

The easiest way to define the generalization of the inner product offered by mat_gen_dim is by stating that it is the contraction of the outer product. However, that is not an efficient plan for calculating the inner product. The following function uses a more direct approach.

The parameter which requires explanation. Had the outer product been calculated, its form would have been the catenation of the forms of the two input matrices. For instance:

    form const frm_a {blt{3,7},blt{2,5},blt{3,7}};
    form const frm_b {blt{3,6},blt{3,7}};
    form const catenation {blt{3,7},blt{2,5},blt{3,7},blt{3,6},blt{3,7}};
Because the catenation has five elements, so must the which parameter. This parameter has the same effect as in contraction. In particular, there are three positions in which which is true, and all of them line up with equal blts (3 =< 7) in the corresponding positions of the catenated form. Also, within the blts for the contraction positions, the top value must be strictly greater than the bottom value. The reason for this is the same as for the plain contraction function.
template <
    typename mul_oper,
    typename add_asgn_oper,
    typename compo_a,
    typename compo_b = compo_a,
    typename compo_y = compo_a,
    typename compo_z = compo_a,
    typename alloc_a = std::allocator <compo_a>,
    typename alloc_b = std::allocator <compo_b>,
    typename alloc_y = std::allocator <compo_y>,
    typename alloc_z = std::allocator <compo_z>
> var_matrix<compo_z,alloc_z> inner_product (
    sub_matrix_base<compo_a,alloc_a> const & mat_a,
    sub_matrix_base<compo_b,alloc_b> const & mat_b,
    vec_bool const & which
);
As an example, this program:
#include "SOME_DIRECTORY/mat_gen_dim.h"
using namespace mat_gen_dim;

form const frm_a {blt{3,7},blt{2,5},blt{3,7}};
form const frm_b {blt{3,6},blt{3,7}};
vec_bool const which {true,false,true,false,true};

struct mul_double {
    double operator() (double const a, double const b) { return a * b; }
};

struct add_asgn_double {
    double operator() (double & z, double const y) { return z += y; }
};

int main() {
    cout.setf (std::ios::fixed, std::ios::floatfield);
    cout.precision (4);

    rand_double const rd_a {0.0, 1.0};
    con_matrix<double> mat_a {sub_matrix_random (frm_a,rd_a)};
    cout << "\n matrix a: " << mat_a;
    con_matrix<double> mat_acon {mat_a};

    rand_double const rd_b {1.0, 2.0};
    con_matrix<double> mat_b {sub_matrix_random (frm_b,rd_b)};
    cout << "\n matrix b: " << mat_b;
    con_matrix<double> mat_bcon {mat_b};

    con_matrix<double> const mat_z
        { inner_product<mul_double, add_asgn_double> (mat_acon, mat_b, which) };
    cout << "\n inner product of a and b: " << mat_z;

    return 0;
}
yields this output:
 matrix a: 
    ( 3 2 3 ) = 0.0850    ( 3 2 4 ) = 0.8916    ( 3 2 5 ) = 0.1897    ( 3 2 6 ) = 0.3980
    ( 3 3 3 ) = 0.7435    ( 3 3 4 ) = 0.5604    ( 3 3 5 ) = 0.8096    ( 3 3 6 ) = 0.5117
    ( 3 4 3 ) = 0.9951    ( 3 4 4 ) = 0.9666    ( 3 4 5 ) = 0.4261    ( 3 4 6 ) = 0.6530
    ( 4 2 3 ) = 0.9615    ( 4 2 4 ) = 0.8580    ( 4 2 5 ) = 0.2940    ( 4 2 6 ) = 0.4146
    ( 4 3 3 ) = 0.5149    ( 4 3 4 ) = 0.7898    ( 4 3 5 ) = 0.5443    ( 4 3 6 ) = 0.0936
    ( 4 4 3 ) = 0.4323    ( 4 4 4 ) = 0.8449    ( 4 4 5 ) = 0.7728    ( 4 4 6 ) = 0.1919
    ( 5 2 3 ) = 0.7804    ( 5 2 4 ) = 0.1813    ( 5 2 5 ) = 0.5791    ( 5 2 6 ) = 0.3141
    ( 5 3 3 ) = 0.4120    ( 5 3 4 ) = 0.9923    ( 5 3 5 ) = 0.1639    ( 5 3 6 ) = 0.3348
    ( 5 4 3 ) = 0.0762    ( 5 4 4 ) = 0.1745    ( 5 4 5 ) = 0.0373    ( 5 4 6 ) = 0.4674
    ( 6 2 3 ) = 0.6741    ( 6 2 4 ) = 0.0667    ( 6 2 5 ) = 0.3898    ( 6 2 6 ) = 0.1654
    ( 6 3 3 ) = 0.9908    ( 6 3 4 ) = 0.8706    ( 6 3 5 ) = 0.6727    ( 6 3 6 ) = 0.5877
    ( 6 4 3 ) = 0.2550    ( 6 4 4 ) = 0.5930    ( 6 4 5 ) = 0.2717    ( 6 4 6 ) = 0.2705
 matrix b: 
    ( 3 3 ) = 1.0850    ( 3 4 ) = 1.8916    ( 3 5 ) = 1.1897    ( 3 6 ) = 1.3980
    ( 4 3 ) = 1.7435    ( 4 4 ) = 1.5604    ( 4 5 ) = 1.8096    ( 4 6 ) = 1.5117
    ( 5 3 ) = 1.9951    ( 5 4 ) = 1.9666    ( 5 5 ) = 1.4261    ( 5 6 ) = 1.6530
 inner product of a and b: 
    ( 2 3 ) = 2.6355    ( 2 4 ) = 2.7851    ( 2 5 ) = 2.9563
    ( 3 3 ) = 3.3173    ( 3 4 ) = 3.7138    ( 3 5 ) = 4.2418
    ( 4 3 ) = 3.1005    ( 4 4 ) = 3.5297    ( 4 5 ) = 4.1472