ai-techsystems/deepC

Python reverse operators (like __radd__) are not working with 'swig -builtin'

Closed this issue · 2 comments

Description

Python allows to overload operators in normal and reverse fashion.

Given, x=dc.arange(5), y=x+1 calls dnnc tensor operator+ (aka __add__ operator), whereas y=1+x calls dnnc tensor reverse operator + (aka __radd__ operator).

If you compile with swig -builtin OR make FAST_SWIG=n for performance reasons, reverse operators stop working.

How to Reproduce

Script: bug.py

import dnnc as dc

x=dc.arange(4)
y=x+1;              # works
y=1+x;              # fails with swig -builtin
print("PASS :-)")

% make clean; make
% python bug.py

Traceback (most recent call last):
  File "bug.py", line 5, in <module>
    y=1+x; #fails with swig -builtin
TypeError: unsupported operand type(s) for +: 'int' and 'dnnc.fTensor'

% make clean ; make FAST_SWIG=n
% python bug.py

PASS :-)

Swig doesn't support __radd__ if you are using -bulitin

Mentioned here, SWIG (Python builtin limitations)

Reverse binary operators (e.g., radd) are not supported.

To illustrate this point, if you have a wrapped class called MyString, and you want to use instances of MyString interchangeably with native python strings, you can define an 'operator+ (const char*)' method :

class MyString {
public:
    MyString (const char *init);
    MyString operator+ (const char *other) const;
    ...
};

SWIG will automatically create an operator overload in python that will allow this:

from MyModule import MyString

mystr = MyString("No one expects")
episode = mystr + " the Spanish Inquisition"

This works because the first operand (mystr) defines a way to add a native string to itself. However, the following will not work:

from MyModule import MyString

mystr = MyString("Parrot")
episode = "Dead " + mystr

The above code fails, because the first operand -- a native python string -- doesn't know how to add an instance of MyString to itself.

Closing this as the solution is described in the previous comment.