home

This function contracts a matrix according to a supplied `vec_bool` = `std::vector<bool>`. This vector must have one component for each dimension of the input matrix, with the value *true* in each subscript position in which contraction is desired to be done.

The input matrix's `form` must have equal `blt`s in all the contraction positions; the other `blt`s need not equal each other or anything else. Also, within the contraction `blt`s, the top value must be strictly greater than the bottom value. There is a subtle reason for this latter requirement: with a zero-length `blt`, the function would have to return the additive identity of the component type, and many types that are not plain old numbers do not have such an identity. Examples:

- When the component type is
`bool`, there is a question whether the "additive" identity should be*false*, which is appropriate in the context of`operator&&`; or*true*, which is suitable for`operator||`. Meanwhile,`operator==`does not have an identity. - When the component type is a matrix itself, such as
`var_matrix<double>`, a component matrix for the additive identity would naturally be full of zeros. However, the`form`of that matrix would be indefinite, and`mat_gen_dim`expects every matrix to have a well-defined`form`.

Related is the case where all the `vec_bool`'s components are *false*: the output matrix cannot exist. It would have the same form as the input, and every component would be zero, but there is no guarantee that the component type has an additive identity, so this case is barred. If by contrast all the `vec_bool`'s components are *true*, there is no problem. The output matrix will have zero dimensions, and its one component will be the sum of components on the input's principal diagonal; this is a generalized trace.

The output matrix has one dimension for each *false* in the `vec_bool`, and its `form`'s `blt`s are taken from the input matrix's `form`'s `blt`s corresponding to the *false* vector positions.

Each component of the output matrix is loaded with the sum of certain components of the input matrix. Those input components are the ones where:

- the subscripts in the non-contractive positions are equal to the corresponding subscripts of the recipient output component; and
- the subscripts in the contractive positions are all equal to each other.

If the `vec_bool` has at least two *true*s, not all the components of the input matrix will be added into an output component; some will be ignored. This is the source of the inefficiency in calculating an inner product by contracting an outer product: many of the results of the outer product operation are simply never used.

The programmer may supply any desired addition function.

Here is the signature of `contraction`:

template < typename add_asgn_oper, typename compo_y, typename compo_z = compo_y, typename alloc_y = std::allocator <compo_y>, typename alloc_z = std::allocator <compo_z> > var_matrix<compo_z,alloc_z> contraction ( sub_matrix_base<compo_y,alloc_y> const & mat_y, 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{1,3},blt{4,7},blt{1,3},blt{5,8},blt{1,3}}; vec_bool const which {true,false,true,false,true}; struct add_asgn_double { double operator() (double & z, double const y) { return z += y; } }; int main() { var_matrix<double> mat_a {sub_matrix_linear (frm_a,0.0)}; cout << "\n matrix a: " << mat_a; con_matrix<double> mat_acon {mat_a}; var_matrix<double> const mat_z { mat_gen_dim::contraction<add_asgn_double> (mat_a, which) }; cout << "\n contraction: " << mat_z; return 0; }yields this annotated output:

matrix a: ( 1 4 1 5 1 ) = 0.14151 ( 1 4 1 5 2 ) = 0.14152 ( 1 4 1 6 1 ) = 0.14161 ( 1 4 1 6 2 ) = 0.14162 ( 1 4 1 7 1 ) = 0.14171 ( 1 4 1 7 2 ) = 0.14172 ( 1 4 2 5 1 ) = 0.14251 ( 1 4 2 5 2 ) = 0.14252 ( 1 4 2 6 1 ) = 0.14261 ( 1 4 2 6 2 ) = 0.14262 ( 1 4 2 7 1 ) = 0.14271 ( 1 4 2 7 2 ) = 0.14272 ( 1 5 1 5 1 ) = 0.15151 ( 1 5 1 5 2 ) = 0.15152 ( 1 5 1 6 1 ) = 0.15161 ( 1 5 1 6 2 ) = 0.15162 ( 1 5 1 7 1 ) = 0.15171 ( 1 5 1 7 2 ) = 0.15172 ( 1 5 2 5 1 ) = 0.15251 ( 1 5 2 5 2 ) = 0.15252 ( 1 5 2 6 1 ) = 0.15261 ( 1 5 2 6 2 ) = 0.15262 ( 1 5 2 7 1 ) = 0.15271 ( 1 5 2 7 2 ) = 0.15272 ( 1 6 1 5 1 ) = 0.16151 ( 1 6 1 5 2 ) = 0.16152 ( 1 6 1 6 1 ) = 0.16161 ( 1 6 1 6 2 ) = 0.16162 ( 1 6 1 7 1 ) = 0.16171 ( 1 6 1 7 2 ) = 0.16172 ( 1 6 2 5 1 ) = 0.16251 ( 1 6 2 5 2 ) = 0.16252 ( 1 6 2 6 1 ) = 0.16261 ( 1 6 2 6 2 ) = 0.16262 ( 1 6 2 7 1 ) = 0.16271 ( 1 6 2 7 2 ) = 0.16272 ( 2 4 1 5 1 ) = 0.24151 ( 2 4 1 5 2 ) = 0.24152 ( 2 4 1 6 1 ) = 0.24161 ( 2 4 1 6 2 ) = 0.24162 ( 2 4 1 7 1 ) = 0.24171 ( 2 4 1 7 2 ) = 0.24172 ( 2 4 2 5 1 ) = 0.24251 ( 2 4 2 5 2 ) = 0.24252 ( 2 4 2 6 1 ) = 0.24261 ( 2 4 2 6 2 ) = 0.24262 ( 2 4 2 7 1 ) = 0.24271 ( 2 4 2 7 2 ) = 0.24272 ( 2 5 1 5 1 ) = 0.25151 ( 2 5 1 5 2 ) = 0.25152 ( 2 5 1 6 1 ) = 0.25161 ( 2 5 1 6 2 ) = 0.25162 ( 2 5 1 7 1 ) = 0.25171 ( 2 5 1 7 2 ) = 0.25172 ( 2 5 2 5 1 ) = 0.25251 ( 2 5 2 5 2 ) = 0.25252 ( 2 5 2 6 1 ) = 0.25261 ( 2 5 2 6 2 ) = 0.25262 ( 2 5 2 7 1 ) = 0.25271 ( 2 5 2 7 2 ) = 0.25272 ( 2 6 1 5 1 ) = 0.26151 ( 2 6 1 5 2 ) = 0.26152 ( 2 6 1 6 1 ) = 0.26161 ( 2 6 1 6 2 ) = 0.26162 ( 2 6 1 7 1 ) = 0.26171 ( 2 6 1 7 2 ) = 0.26172 ( 2 6 2 5 1 ) = 0.26251 ( 2 6 2 5 2 ) = 0.26252 ( 2 6 2 6 1 ) = 0.26261 ( 2 6 2 6 2 ) = 0.26262 ( 2 6 2 7 1 ) = 0.26271 ( 2 6 2 7 2 ) = 0.26272 contraction: ( 4 5 ) = 0.38403 = ( 1 4 1 5 1 ) + ( 2 4 2 5 2 ) ( 4 6 ) = 0.38423 = ( 1 4 1 6 1 ) + ( 2 4 2 6 2 ) ( 4 7 ) = 0.38443 = ( 1 4 1 7 1 ) + ( 2 4 2 7 2 ) ( 5 5 ) = 0.40403 = ( 1 5 1 5 1 ) + ( 2 5 2 5 2 ) ( 5 6 ) = 0.40423 = ( 1 5 1 6 1 ) + ( 2 5 2 6 2 ) ( 5 7 ) = 0.40443 = ( 1 5 1 7 1 ) + ( 2 5 2 7 2 ) ( 6 5 ) = 0.42403 = ( 1 6 1 5 1 ) + ( 2 6 2 5 2 ) ( 6 6 ) = 0.42423 = ( 1 6 1 6 1 ) + ( 2 6 2 6 2 ) ( 6 7 ) = 0.42443 = ( 1 6 1 7 1 ) + ( 2 6 2 7 2 )