On Sat, 28 Oct 2006 17:49:07 -0700, David Harvey  
<[EMAIL PROTECTED]> wrote:
> I've been looking carefully at the RingElement__add__ code some more,
> in light of some of the issues William brought up last week, and my
> conclusion is that it's still not right.
>
> Part of the design was supposed to be that a highly optimised piece
> of pyrex code could call _add_sibling_cdef for any RingElement-
> derived type, to achieve maximum performance even for a generic type.
> But that's still broken in the current model, i.e. in the same
> scenario William thought up, which is a python class derived from
> Integer; it would be calling Integer's _add_sibling_cdef, instead of
> some _add_sibling python function provided in the derived class.
> Therefore, such a highly optimised algorithm wouldn't work on such a
> type.

A Python class can't call _add_sibling_cdef.  You mean a Pyrex class
calling what it hopes is the _add_sibling_cdef method of the Python
class and instead getting the method of the parent?  This could be
a problem.

> There's only one way I can think of to get around this, short of
> dropping some of the desirable properties we want the system to have.
>
> We need to introduce yet *another* cdef function, which I will call
> add_sibling_dispatch. (This solution may have been what Martin
> proposed in a Seattle coffee shop, although I was too confused at the
> time to understand what he was saying.)
>
> All these functions would behave as follows:
>
> =========================================
>
> (1)
> __add__ will only call add_sibling_dispatch; it doesn't call either
> _add_sibling or _add_sibling_cdef as it does currently.
>
> (2)
> The default implementation of _add_sibling_cdef in RingElement is to
> raise NotImplementedError.
>
> (3)
> The default implementation of _add_sibling in RingElement is to call
> _add_sibling_cdef. No pyrex classes are allowed to override this.

The latter is by convention.  We'll need a big comment to make that clear.

> (4)
> add_sibling_dispatch decides whether to call _add_sibling or
> _add_sibling_cdef. It does this as follows:
>
> if HAS_DICTIONARY(self):
>     self._add_sibling(other)
> else:
>     self._add_sibling_cdef(other)
>
> (Even better would be if it could tell whether "self" has an
> implementation of _add_sibling which is not the default RingElement
> one, before trying to call it. We have code in there now that does
> this, but actually it's broken, because it doesn't take into account
> methods attached directly to the instance; it only looks for methods
> attached to the instance's class.)
>
> (5)
> No-one is allowed to call _add_sibling_cdef directly, except for
> add_sibling_dispatch.They should call add_sibling_dispatch instead.
> There's a speed hit here, which is unfortunate. (Well actually, if a
> specific piece of code knows the *exact* type of its variables, it
> could call _add_sibling_cdef directly if it wanted to, for a tiny bit
> of extra speed.)

So to write optimized code, one calls add_sibling_dispatch instead
of _add_sibling_cdef.  Otherwise everything is basically the same
as your previous proposal (modulo some code refactoring).   May
I suggested

           fast_add

instead of add_sibling_dispatch for the name of the Pyrex method?
It will only be visible from Pyrex code so no underscore is needed,
but will get used a lot in code we write later, so it shouldn't be
too long (and add_sibling_dispatch) is too long.   We'llhave

     cdef fast_add(self, ...)
     cdef fast_mul(self,...
     cdef fast_div(self,...)
     cdef fast_sub(self....)

Another option would be to call them

     cdef add_unsafe(self,...)
     cdef mul_unsafe(self,...)

etc., since the point is that you're doing addition but without any
typing checking or coercion at all, and by writing unsafe it will make
any coder or reader of that code look double carefully at it.  I've
made the get and set methods for matrices pyrexed methods named
get_unsafe and set_unsafe.

> =========================================
>
> In other words, add_sibling_dispatch is simulating function
> overrides. (Talk about getting into the language design business.)

It's implementing it not simulating it.   I am opposed to language
design in the sense of "writing a new interpreter from scratch
for mathematics", which is why I chose Python/Pyrex.  Beyond that,
the goals of SAGE are to be an "incredible high quality free
mathematics software system", and I think we should use any and
all tools and ideas at our disposal in order to attain that goal.
If some language design is necessary, then let's do it (and do it
right).


William

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/
-~----------~----~----~----~------~----~------~--~---

Reply via email to