[Numpy-discussion] numpy1.2 : make sorts unary ufuncs

Charles R Harris charlesr.harris@gmail....
Sat Apr 19 02:46:22 CDT 2008


On Sat, Apr 19, 2008 at 1:29 AM, Charles R Harris <charlesr.harris@gmail.com>
wrote:
<snip>

>
> On Sat, Apr 19, 2008 at 1:12 AM, Robert Kern <robert.kern@gmail.com>
> wrote:
>
> > On Sat, Apr 19, 2008 at 1:55 AM, Charles R Harris
> > <charlesr.harris@gmail.com> wrote:
> >
> > > Yes, but the inner loop is just something that uses the array values
> > along
> > > that axis to produce another set of values, i.e., it is a vector
> > valued
> > > function of vectors. So is a sort, so is argsort, so is the inner
> > product,
> > > so on and so forth. That's what we have here:
> > >
> > > typedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp
> > *,
> > > void *);
> > >
> > >  No difference that I can see. It is the call function in
> > PyUFuncObject that
> > > matters.
> >
> > I believe this is the disconnect. From my perspective, the fact that
> > the inner kernel function of a ufunc has a sufficient argument list to
> > do a sort isn't important. The signature of that kernel function isn't
> > what makes a ufunc; it's all of the code around it that does
> > broadcasting, type matching and manipulation, etc. If we're changing
> > that code to accommodate sorting, we haven't gained anything. We've
> > just moved some code around; possibly we've reduced the line count,
> > but I fear that we will muddy ufunc implementation with non-ufunc
> > functionality and special cases.
> >
> > If you want to go down this road, I think you need to do what Travis
> > suggests: factor out some of the common code between ufuncs and sorts
> > into a "superclass" (not really, but you get the idea), and then
> > implement ufuncs and sorts based on that. I think trying to shove
> > sorts into ufuncs-qua-ufuncs is a bad idea. There is more than one
> > path to code reuse.
> >
>
> Right now we have:
>
> typedef struct {
>     PyObject_HEAD
>     int nin, nout, nargs;
>     int identity;
>     PyUFuncGenericFunction *functions;
>     void **data;
>     int ntypes;
>     int check_return;
>     char *name, *types;
>     char *doc;
>     void *ptr;
>     PyObject *obj;
>     PyObject *userloops;
> } PyUFuncObject;
>
> Which could be derived from something slightly more general. We could also
> leave out reduce, accumulate, etc., which are special cases. We then have
> common code for registration, etc. The call function still has to check
> types, dispatch the calls for the axis, maybe create output arrays, as for
> maximum.reduce, and so on. Broadcasting isn't applicable to unary type
> things and many functions, say in argsort, look unary from the top, so that
> doesn't enter in.
>

For instance

static void
BOOL_@kind@(char **args, intp *dimensions, intp *steps, void *func)
{
    register intp i;
    intp is1=steps[0],is2=steps[1],os=steps[2], n=dimensions[0];
    char *i1=args[0], *i2=args[1], *op=args[2];
    Bool in1, in2;
    for(i=0; i<n; i++, i1+=is1, i2+=is2, op+=os) {
        in1 = (*((Bool *)i1) != 0);
        in2 = (*((Bool *)i2) != 0);
        *((Bool *)op)= in1 @OP@ in2;
    }
}

It looks to me like broadcasting is achieved by adjusting the step size. The
only bothersome detail here is getting the count from the first dimension,
that looks a bit fragile.

Chuck
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/numpy-discussion/attachments/20080419/67d26197/attachment.html 


More information about the Numpy-discussion mailing list