Creates a new binary special method with left and right versions, such as
        A.__mul__(B) <=> A*B,
        A.__rmul__(B) <=> [B*A if B.__mul__(A) fails]
    for target class. The method is called __op_name__.

def create_rl_lin_comb_method(op_name, klass, x_roles, y_roles):
    """
    Creates a new binary special method with left and right versions, such as
        A.__mul__(B) <=> A*B,
        A.__rmul__(B) <=> [B*A if B.__mul__(A) fails]
    for target class. The method is called __op_name__.
    """
    # This function will became the methods.

    def new_method(self, other, x_roles=x_roles, y_roles=y_roles):
        if not check_special_methods():
            raise NotImplementedError(
                'Special method %s called on %s, but special methods have been disabled. Set pymc.special_methods_available to True to enable them.' %
                (op_name, str(self)))
        x = []
        y = []
        for xr in x_roles:
            if xr == 'self':
                x.append(self)
            elif xr == 'other':
                x.append(other)
            else:
                x.append(xr)
        for yr in y_roles:
            if yr == 'self':
                y.append(self)
            elif yr == 'other':
                y.append(other)
            else:
                y.append(yr)
        # This code will create one of two Deterministic objects.
        return LinearCombination(
            '(' + '_'.join([self.__name__, op_name, str(other)]) + ')', x, y, trace=False, plot=False)

    # Convert the functions into methods for klass.
    new_method.__name__ = '__' + op_name + '__'
    setattr(
        klass,
        new_method.__name__,
        UnboundMethodType(
            new_method,
            None,
            klass))