Discussion:
Negative array indices
(too old to reply)
b_gom
2010-12-02 21:54:41 UTC
Permalink
I've been stumbling around trying to figure out uses for the negative
array indexing in IDL 8. As usual, the documentation doesn't fully
describe the logic behind the syntax rules.

One rule that I've discovered is that negative array indices shouldn't
be thought of as indices 'rolling over' as you cross zero. For
example:
If x=findgen(10), then x[-1] is the same as x[9], and x[-10] is the
same as x[0], but x[-11] isn't allowed. I can see why this follows
from not allowing positive indices greater than the number of elements
in x.

I guess this leads to this behaviour:
IDL> x=findgen(10)
IDL> print,x[-4:0]
% Illegal subscript range: X.

because this gets translated to:
IDL> print,x[6,0]
which isn't allowed.

Now, on to the real question. Why does the following not work:

IDL> print,x[1:3]
1.00000 2.00000 3.00000
IDL> print,x[[1,2,3]]
1.00000 2.00000 3.00000
IDL> print,x[-3:-1]
7.00000 8.00000 9.00000
IDL> print,x[[-3,-2,-1]]
0.000000 0.000000 0.000000
Michael Galloy
2010-12-02 22:15:22 UTC
Permalink
Post by b_gom
I've been stumbling around trying to figure out uses for the negative
array indexing in IDL 8. As usual, the documentation doesn't fully
describe the logic behind the syntax rules.
One rule that I've discovered is that negative array indices shouldn't
be thought of as indices 'rolling over' as you cross zero. For
If x=findgen(10), then x[-1] is the same as x[9], and x[-10] is the
same as x[0], but x[-11] isn't allowed. I can see why this follows
from not allowing positive indices greater than the number of elements
in x.
IDL> x=findgen(10)
IDL> print,x[-4:0]
% Illegal subscript range: X.
IDL> print,x[6,0]
which isn't allowed.
IDL> print,x[1:3]
1.00000 2.00000 3.00000
IDL> print,x[[1,2,3]]
1.00000 2.00000 3.00000
IDL> print,x[-3:-1]
7.00000 8.00000 9.00000
IDL> print,x[[-3,-2,-1]]
0.000000 0.000000 0.000000
It's a bit of a strange story, but this last one "print, x[[-3,-2,-1]]"
was actually allowed before IDL 8.0, so the behavior had to match up to
maintain backward compatibility. It had nothing to do with counting back
from the end of the array, instead it just checked bounds of index
arrays and used the closest valid index, in your case 0. It would work
similarly if you did:

IDL> print, x[[10, 10, 10]]
9.00000 9.00000 9.00000

Mike
--
www.michaelgalloy.com
Research Mathematician
Tech-X Corporation
David Fanning
2010-12-02 22:50:40 UTC
Permalink
Post by b_gom
I've been stumbling around trying to figure out uses for the negative
array indexing in IDL 8. As usual, the documentation doesn't fully
describe the logic behind the syntax rules.
It's always a bad sign when you are stumbling around trying
to figure out how to use a feature you never realized you
needed before. Or are you trying to write a book, too?

Cheers,

David
--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Sepore ma de ni thui. ("Perhaps thou speakest truth.")
b_gom
2010-12-03 00:35:56 UTC
Permalink
Post by David Fanning
It's always a bad sign when you are stumbling around trying
to figure out how to use a feature you never realized you
needed before. Or are you trying to write a book, too?
No, that market has already been cornered.

It was more a case of: 'Ah, this might be a situation where those new
negative indices I read about might simplify things', followed quickly
by the realisation that I didn't really understand what they were good
for.

In general, it would be helpful if the IDL documentation went a bit
further than just describing the syntax and calling sequence for the
operators, commands and routines, and added a paragraph or two for
each saying "And here's what it is\isn't good for:"

Another example is the new list and hash objects. The documentation
does a good job describing what their methods do, but doesn't really
explain what they are better for than arrays and structures, and what
performance trade-offs to be aware of. I guess that is where your new
book comes in..
Paulo Penteado
2010-12-03 01:28:07 UTC
Permalink
Post by b_gom
Another example is the new list and hash objects. The documentation
does a good job describing what their methods do, but doesn't really
explain what they are better for than arrays and structures, and what
performance trade-offs to be aware of. I guess that is where your new
book comes in..
I had not even noticed that the documentation did not mention
motivation. Maybe all the many requests for lists, hashes and negative
indices over the years (mine, for one) left them with the impression
that everyone already wanted them. Negative indices are a good
syntatic sugar (basically and abbreviation for things like
a[n_elements(a)-1] and b[0,(size(b,/dimensions))[1]-1]), and I find
them very useful, but they are not even close in importance to lists
and hashes. I was leaving IDL for Python because of the lack of lists
and hashes.

In nearly every program I write I need a dynamic, possibly
heterogeneous container. Without lists, it is too much work to have to
predict or alter the dimensions of arrays, or handle (particularly,
read) several layers of indirection through nested pointer arrays. And
I usually have a bunch of different variables to keep associated,
where structures are too awkward to use because their are static.
Usually because the code needs to deal with data that can come in
varied forms, not known at compile time (being a dynamically typed
language is one the main factors in my choice to use IDL).
Paulo Penteado
2010-12-03 01:40:58 UTC
Permalink
Post by b_gom
IDL> x=findgen(10)
IDL> print,x[-4:0]
% Illegal subscript range: X.
IDL> print,x[6,0]
which isn't allowed.
Not allowed just because you are trying to decrease the index with a
positive stride (it will never get to 0 starting from 5 and adding
increments of 1). This does work:

IDL> x=findgen(10)
IDL> print,x[-4:0:-1]
6.00000 5.00000 4.00000 3.00000 2.00000
1.00000 0.00000
IDL> print,x[6:0:-1]
6.00000 5.00000 4.00000 3.00000 2.00000
1.00000 0.00000

Loading...