[bug?] UserLong.py - pow(5, UserLong(3), 26) fails
hiya people, been a while, i'm back onto python exploration for a serious monster exciting parallelisation project. as part of the evaluation, i have created UserLong.py, and am working my way through the list of all operations. i may have some mistakes and/or missing operators, and am trying to work this one out. at the bottom of the file are some inline debug tests. one of these - pow(int(5), UserLong(3), 26) - is failing: Script started on Wed May 1 19:06:30 2002 highfield:/usr/local/lib/python2.2# python UserLong.py int 3 long 3 5**int(y) 125 5**y rpow: (5,) 3 x^y%26 (3L, 26) 21L 5^y%26 Traceback (most recent call last): File "UserLong.py", line 153, in ? print "5^y%26", pow(5, y, 26) TypeError: unsupported operand type(s) for pow(): 'int', 'instance', 'int' highfield:/usr/local/lib/python2.2# Script done on Wed May 1 19:06:37 2002 now, if i read this correctly, what is happening is that in the [optimised] code, Objects/intobject.c, support for types other than int, float and long - via the macro CONVERT_TO_LONG - are simply not supported. this i believe can be demonstrated to be so because if you do pow(5, [], 26) you get the same error except replace 'instance' above with 'list'. now, could someone with a little more knowledge than i kindly evaluate, if they have the time, whether: - _is_ this happening because i have missed out a function in UserLong.py that i do not know the name of? or: - _is_ this due to a bug in intobject.c's int_pow() or: - _is_ this due to a bug in the implementation of the pow() "spam" function? - other? many thanks, luke -- ---------------------------------------------------------- this message is private, confidential, and is intented for the specified recipients only. if you received in error, altered, deleted, modified, destroyed or interfered with the contents of this message, in whole or in part, please inform the sender (that's me), immediately. if you, the recipient, reply to this message, and do not then receive a response, please consider your reply to have been lost or deliberately destroyed: i *always* acknowledge personal email received. please therefore take appropriate action and use appropriate protocols to ensure effective communication. thank you.
"""A more or less complete user-defined wrapper around long objects.""" class UserLong: def __init__(self, initlong=None): self.data = 0L if initlong is not None: # XXX should this accept an arbitrary sequence? if type(initlong) == type(self.data): self.data = initlong elif isinstance(initlong, UserLong): self.data = initlong.data else: self.data = long(initlong) def __repr__(self): return repr(self.data) def __lt__(self, other): return self.data < self.__cast(other) def __le__(self, other): return self.data <= self.__cast(other) def __eq__(self, other): return self.data == self.__cast(other) def __ne__(self, other): return self.data != self.__cast(other) def __gt__(self, other): return self.data > self.__cast(other) def __ge__(self, other): return self.data >= self.__cast(other) def __cast(self, other): if isinstance(other, UserLong): return other.data else: return other def __long__(self): return self.data def __int__(self): return int(self.data) def __cmp__(self, other): return cmp(self.data, self.__cast(other)) def __sub__(self, other): if isinstance(other, UserLong): return self.__class__(self.data - other.data) elif isinstance(other, type(self.data)): return self.__class__(self.data - other) else: return self.__class__(self.data - long(other)) def __add__(self, other): if isinstance(other, UserLong): return self.__class__(self.data + other.data) elif isinstance(other, type(self.data)): return self.__class__(self.data + other) else: return self.__class__(self.data + long(other)) def __rsub__(self, other): if isinstance(other, UserLong): return self.__class__(other.data - self.data) elif isinstance(other, type(self.data)): return self.__class__(other - self.data) else: return self.__class__(long(other) - self.data) def __radd__(self, other): if isinstance(other, UserLong): return self.__class__(other.data + self.data) elif isinstance(other, type(self.data)): return self.__class__(other + self.data) else: return self.__class__(long(other) + self.data) def __iadd__(self, other): if isinstance(other, UserLong): self.data += other.data elif isinstance(other, type(self.data)): self.data += other else: self.data += long(other) return self def __isub__(self, other): if isinstance(other, UserLong): self.data -= other.data elif isinstance(other, type(self.data)): self.data -= other else: self.data -= long(other) return self def __pow__(self, *args): print args if len(args) == 1: (other,) = args if isinstance(other, UserLong): return self.__class__(pow(self.data, other.data)) elif isinstance(other, type(self.data)): return self.__class__(pow(self.data, other)) else: return self.__class__(pow(self.data, long(other))) elif len(args) == 2: (other, other2) = args if isinstance(other, UserLong): x = other.data elif isinstance(other, type(self.data)): x = other else: x2 = long(other) if isinstance(other2, UserLong): x2 = other2.data elif isinstance(other2, type(self.data)): x2 = other2 else: x2 = long(other2) return self.__class__(pow(self.data, x, x2)) def __rpow__(self, *args): print "rpow:", args return self.data def __mod__(self, other): if isinstance(other, UserLong): return self.__class__(self.data % other.data) elif isinstance(other, type(self.data)): return self.__class__(self.data % other) else: return self.__class__(self.data % long(other)) def __rmod__(self, other): if isinstance(other, UserLong): return self.__class__(other.data % self.data) elif isinstance(other, type(self.data)): return self.__class__(other % self.data) else: return self.__class__(long(other) % self.data) def __divmod__(self, m): return self.__class__(divmod(self.data, m)) def __div__(self, n): return self.__class__(self.data/n) def __rdiv__(self, n): return self.__class__(n/self.data) def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ def __imul__(self, n): self.data *= n return self def __and__(self, n): return self.__class__(self.data&n) __rand__ = __and__ def __iand__(self, n): self.data &= n return self x = UserLong(5L) y = UserLong(3L) print "int", int(y) print "long", long(y) print "5**int(y)", 5 ** int(y) print "5**y", 5 ** y print "x^y%26", pow(x, y, 26) print "5^y%26", pow(5, y, 26) print "x^3%26", pow(x, 3, 26) print x % y print 5 % y print x % 3 print "x-y", x - y print "5-y", 5 - y print "x-3", x - 3 print "x/y", x / y print "5/y", 5 / y print "x/3", x / 3
On Wed, May 01, 2002 at 07:14:14PM +0000, Luke Kenneth Casson Leighton wrote:
as part of the evaluation, i have created UserLong.py, and am working my way through the list of all operations.
one of these - pow(int(5), UserLong(3), 26) - is failing
further preliminary analysis shows that the error message is being reported from Objects/abstract.c:ternary_op.c. without doing any debugging, i presume that PyNumber_Coerce and the macro NEW_STYLE_NUMBER are both failing to identify "class UserLong" as supporting numerical operations. now, there _may_ be some way to add an operator to class UserLong which identifies it as a "number" - i don't know what it is. anyone know? PyNumber_Coerce requires that the HOF table (PyObject*)w->ob_type->tp_as_number be != NULL in order for it to call tp_as_number->nb_coerce() and _that_ apparently will give number coercion. however, that means that _even_ if i define "__coerce__" in class UserLong, it won't get called because tp_as_number is an optimisation/speedup HOF table of functions, yes? so, the check in PyNumber_Coerce needs to also have "if (tp_as_number == NULL) lookup_function("__coerce__") and call it" am i right? l. -- ---------------------------------------------------------- this message is private, confidential, and is intented for the specified recipients only. if you received in error, altered, deleted, modified, destroyed or interfered with the contents of this message, in whole or in part, please inform the sender (that's me), immediately. if you, the recipient, reply to this message, and do not then receive a response, please consider your reply to have been lost or deliberately destroyed: i *always* acknowledge personal email received. please therefore take appropriate action and use appropriate protocols to ensure effective communication. thank you.
michael, the point of doing a UserLong.py is that it is an easy way to add in profiling and debug info and to evaluate alternative implementations of Long numbers. the ultimate aim is to find out if it is worth adding in support for Aspex Technology's massively parallel signal processor chip as a python co-processor. l.
participants (1)
-
Luke Kenneth Casson Leighton