@local_optimizer([gemm_no_inplace])
def local_gemm_to_gemv(node):
 if (node.op == gemm_no_inplace):
  (z, a, x, y, b) = node.inputs
  if (z.broadcastable == x.broadcastable == (True, False)):
   r = gemv_no_inplace(z.dimshuffle(1), a, y.T, x.dimshuffle(1), b)
   return [r.dimshuffle('x', 0)]
  if (z.broadcastable == y.broadcastable == (False, True)):
   r = gemv_no_inplace(z.dimshuffle(0), a, x, y.dimshuffle(0), b)
   return [r.dimshuffle(0, 'x')]

@ local_optimizer ( [ gemm_no_inplace ] ) def local_gemm_to_gemv ( node ) : if ( node . op == gemm_no_inplace ) : ( z , a , x , y , b ) = node . inputs if ( z . broadcastable == x . broadcastable == ( True , False ) ) : r = gemv_no_inplace ( z . dimshuffle ( 1 ) , a , y . T , x . dimshuffle ( 1 ) , b ) return [ r . dimshuffle ( 'x' , 0 ) ] if ( z . broadcastable == y . broadcastable == ( False , True ) ) : r = gemv_no_inplace ( z . dimshuffle ( 0 ) , a , x , y . dimshuffle ( 0 ) , b ) return [ r . dimshuffle ( 0 , 'x' ) ]
gemm acting on row or column matrices -> gemv .