def block_dot(A, B, diagonal=False):
<EOL>assert A.dtype is np.dtype('<STR_LIT:object>'), "<STR_LIT>"<EOL>assert B.dtype is np.dtype('<STR_LIT:object>'), "<STR_LIT>"<EOL>assert A.shape == B.shape<EOL>def f(C,D):<EOL><INDENT>"""<STR_LIT>"""<EOL>Cshape = C.shape<EOL>Dshape = D.shape<EOL>if diagonal and (len(Cshape) == <NUM_LIT:1> or len(Dshape) == <NUM_LIT:1>or C.shape[<NUM_LIT:0>] != C.shape[<NUM_LIT:1>] or D.shape[<NUM_LIT:0>] != D.shape[<NUM_LIT:1>]):<EOL><INDENT>print("<STR_LIT>".format(C.shape, D.shape))<EOL>return C*D<EOL><DEDENT>else:<EOL><INDENT>print("<STR_LIT>".format(C.shape, D.shape))<EOL>return np.dot(C,D)<EOL><DEDENT><DEDENT>dot = np.vectorize(f, otypes = [np.object])<EOL>return dot(A,B)<EOL>
Element wise dot product on block matricies

+------+------+   +------+------+    +-------+-------+
|      |      |   |      |      |    |A11.B11|B12.B12|
| A11  | A12  |   | B11  | B12  |    |       |       |
+------+------+ o +------+------| =  +-------+-------+
|      |      |   |      |      |    |A21.B21|A22.B22|
| A21  | A22  |   | B21  | B22  |    |       |       |
+-------------+   +------+------+    +-------+-------+

..Note
    If any block of either (A or B) are stored as 1d vectors then we assume
    that it denotes a diagonal matrix efficient dot product using numpy
    broadcasting will be used, i.e. A11*B11

    If either (A or B) of the diagonal matrices are stored as vectors then a more
    efficient dot product using numpy broadcasting will be used, i.e. A11*B11