[Matrix-SIG] Shifted array ops (was: RE: [Matrix-SIG] QUERY: Array indexing)

Frank Horowitz frank@ned.dem.csiro.au
Fri, 12 Mar 1999 18:25:35 +0800

At 3:29 PM +0800 12/3/99, Tim Peters wrote:
>[Frank Horowitz chews & chews, but is still hungry]
>> My applications require local references in the array (somewhat akin to
>> finite difference/convolution templates) but the operations I need to
>> perform are more general than multiply-and-sum, hence I can't use the
>> recent n-d convolve routines from Travis Oliphant (or was it someone
>> else; senility is obviously setting in...)
>> My approach to date has been to build shifted/rolled versions of the
>> array, and operate with them (code available upon request, if anyone is
>> silly enough to want it :-).  Obviously, this comes at a severe cost in
>> memory ...
>I don't know the best way to approach this in NumPy, perhaps because I
>haven't yet installed it <wink>.  In straight Python I do stuff like this by
>writing thin wrapper classes that leave the original matrices alone, merely
>permuting the *indices* in __setitem__/__getitem__  (instead of physically
>permuting the *data*).  For example, if your need to transpose a 2D array,
>just swap the indices in the wrappers before passing them on to the actual
>(still untransposed) array.
>Here's an overly simplistic but complete example:

<some stuff deleted>

>class VectorRotate:
>    def __init__(self, data, shift):
>        """Make data act as if it had been rotated left by shift slots"""
>        self.x = data
>        self.n = len(data)
>        self.shift = shift
>    def __getitem__(self, i):
>        return self.x[(i + self.shift) % self.n]
>    def __setitem__(self, i, val):
>        self.x[(i + self.shift) % self.n] = val
>    def __len__(self):
>        return self.n
>    def getdata(self):
>        return self.x

>If the above was suggestive enough, I expect you'll find this kind of thing
>easier than gather/scatter.  Yes?

Err, I'm still not sure I quite understand (more chewing sounds evident in
the background; do I feel like a cow, or what? :-).

If I understand your suggestion correctly, you're doing some trickery with
indexing *for an individual element* (i.e. your __getitem__ __setitem__
routines index a specific element).  Does the fact that they're overriding
the operator class methods imply that the result of the calls to getdata
index through the array at C speeds (courtesy of the NumPy __getitem__
support code)?  Or is the result that the getdata indexes through the array
at interpreter speeds?

Remember, I'm contemplating applying this stuff (over and over :-) to
arrays with ~12 million elements.  If it runs at interpreter speeds, I'll
have to look for a different answer.

>> ...
>> Wisdom anyone? (Tim? :-)
>Sorry, you didn't suck up enough to get a wise answer!
OK, then thanks for the half-wise answer! (And I grovel in your general
direction, which I believe must more or less be straight down from here in
Perth :-)

		Frank Horowitz

Frank Horowitz                                      frank@ned.dem.csiro.au
Australian Geodynamics Cooperative Research Centre, and
CSIRO-Exploration & Mining, PO Box 437, Nedlands, WA 6009,       AUSTRALIA
Direct: +61 8 9284 8431;  FAX: +61 8 9389 1906; Reception: +61 8 9389 8421