TMatrixD/TVectorD multiplication in python crashes

How do I use matrix-vector multiplication for the TMatrixD/TVectorD classes form python (ROOT 6.11/03)? I used something like this:

import ROOT
ROOT.gSystem.Load("libMatrix.so")
from ROOT import *

M = TMatrixD(3, 3)
v = TVectorD(3)
M[0][0] = 1.
M[1][1] = 2.
M[2][2] = 3.
v[0] = 1.
v[1] = 1.
v[2] = 1.
w = M * v

The process crashes with Error in <TClingCallFunc::make_wrapper>: Cannot make wrapper for a function templateinstantiation with no body!, and a stack trace (which is likely caused by pyroot not figuring out which overload of operator* to call).
Is there a way to tell pyroot to use the version that Cling seems to find without trouble?

I guess this is bug ROOT-7717. Unfortunately I am not aware of any fixes or workarounds for this.

1 Like

The direct cause of the error is TVectorT.h and TMatrixT.h only containing forward declarations, with the function bodies in the respective .cxx files, thus it is impossible for Cling to instantiate these functions.

It works from the root prompt, b/c all the relevant instantiations are pre-baked in the dictionary. So, the failure is one of lookup. Probably a mismatch in naming (e.g. a comparison of the function name with and without the template arguments). There are several general improvements in that respect in cppyy/master, but I don’t know whether it fixes this specific issue.

For workarounds, use the class-based operators, i.e. __iadd__ and __imul__. The latter is surprising, but looking at the implementation, v *= M actually does v = M*v rather than the syntactically expected but semantically non-sensical v = v*M.

You can also use those to fix up the global operator*, if you care enough (but you have to make sure to deal with the overloading). Something like:

def fixed_add(self, other):
    tmp = self.__class__(self)
    tmp += other
    return tmp

TMatrixD.__add__ = fixed_add

def fixed_mul(self, other):
    if isinstance(other, TVectorD):
        tmp = other.__class__(other)
        tmp *= self
    else:
        tmp = self.__class__(self)
        tmp *= other
    return tmp

TMatrixD.__mul__ = fixed_mul

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.