View License

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video

Highlights from

4.5 | 4 ratings Rate this file 3 Downloads (last 30 days) File Size: 2.69 KB File ID: #30096 Version: 1.5
image thumbnail




19 Jan 2011 (Updated )

convert subscripts to ALL corresponding indices

| Watch this File

File Information

idx = sub2allind(sz, sub1, sub2, sub3, ... )

Like Matlab's sub2ind, sub2allind computes the equivalent linear indices for
given subscripts of an array with size SZ.
Unlike sub2ind, it computes a field of all combinations of
subscripts. So, instead of calling A( 2:3, 1, 4:11) you might
    linIdx = sub2allind( size(A), 2:3, 1, 4:11 );

and then call A(linIdx) or A(linIdx(:)) or you reshape linIdx the way you need.

This is usefull whenever you want to access a subset of an array and compare it with a differently shaped thing, like

A(linIdx(:)) = A(linIdx(:)) + <1D-Vector>

Using the naked colon operator is allowed to reference an entire dimension:

linIdx = sub2allind( sz, :, sub2 );


This file inspired Catpad and N Dimensional Sparse Arrays.

MATLAB release MATLAB 7.12 (R2011a)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (12)
10 Jul 2015 Yung-Yeh

Yung-Yeh (view profile)

I was about to write something similar to this and yet something even better is already here. Great job.

20 Feb 2012 Alexander Stepanov

Very useful, thanks)

26 Jul 2011 Marc

Marc (view profile)

29 Jan 2011 Matt J

Matt J (view profile)

"I wonder if it would be best to make that behaviour default, since you could nevertheless use linIdx(:) if you want it to be a vector."

Perhaps, although if other people have downloaded previous versions of the tool, they might have backward compatibility issues.

Comment only
29 Jan 2011 Michael Völker

Matt, the reshape thing is the easiest, since the indices happen to automatically be in the right shape (plus 1 leading "dummy dimension") before I convert them to a column vector.
I wonder if it would be best to make that behaviour default, since you could nevertheless use linIdx(:) if you want it to be a vector.

Comment only
29 Jan 2011 Matt J

Matt J (view profile)

I like it. It's occurred to me that it will be a good OOP tool for converting the output of the SUBSTRUCT function to a linear index. All the more reason why processing ':' is a good thing. This often comes up in OOP applications where you want to overload SUBSREF or SUBSASGN.

One more tip I had was to enable a syntax
similar to


which would automatically reshape linIdx to be the same shape as A(2:3,1,4:11). That way, A(linIdx) and A(2:3,1,4:11) would produce exactly the same result (in shape as well as in data content).

28 Jan 2011 Michael Völker

(Narf, I meant of course sub2allind(sz,2:3,':'), not A...)

Comment only
28 Jan 2011 Michael Völker

Jos, your ngrid-approach is very cool. The only reason I still do not use it is that it still may explode the memory and take quite long, if the requested field of indices itself is very large.
If the array has N dimensions, ngrid will produce N new arrays each the size of the requested field of subscripts. However, as bsxfun is a quite young function, the ngrid approach should be much more portable.

To be honest, I hardly remember where I used this function the last time, but I think it was at some point where I later figured out I could use accumarray() instead of whatever I tried before. But what I know for sure is that the default sub2ind-behaviour *always* bugged me, because it is simply not what I'd expect from it.
So the primary reason for me to code this, was that I have this functionality I expect, or at least have a sneak in the source later, when I forgot how it works. :-)

Matt, I like your remark, so I utilize ':' now. The funny thing is, that not only A(sz,2:3,':') works, but A(sz,2:3,:) is okay, too. Somehow, the colon seems to become a string, automagically...

Comment only
22 Jan 2011 Matt J

Matt J (view profile)

You might want to consider allowing ':' inputs as well. For example, if you want the linear index corresponding to
A(2:3,:,4:11) then you would call

linIdx = sub2allind( size(A), 2:3, ':', 4:11 );

Also, perhaps I'm not seeing all of the situations where you intend to use this, however, I tend to think that you'll save yourself both CPU time and memory if instead of linear indexing A, you simply reshape your 1D-Vector .

Comment only
21 Jan 2011 Jos (10584)

Jos (10584) (view profile)

Sure, for large arrays, the logical-find method is a waste of memory, especially if you only need a few indices ...
Another, fast and vectorized, option:

function idx = sub2allind(sz, varargin)
[subix{1:nargin-1}] = ndgrid(varargin{:}) ;
idx = sub2ind(sz,subix{:}) ;

Comment only
20 Jan 2011 Michael Völker

Oops, nice... :-)

I had the feeling there should be an easier way...

But nevertheless, I usually work with quite large arrays (some 1E8 entries), where your admittedly very nice code causes a waste of RAM and time since an equal-sized array must be actually created.

With sz=[1E3 1E3 1E3], my version needs about 0.000478 seconds, the find-version takes 1.412256 seconds.

Comment only
20 Jan 2011 Jos (10584)

Jos (10584) (view profile)

What about the alternative code

function idx = sub2allind(sz, varargin)
tf = false(sz) ;
tf(varargin{:}) = true ;
idx = find(tf) ;

Comment only
28 Jan 2011 1.1

* Implemented colon operator (Thanks to Matt J)
* possible errors catched; more comments

06 Sep 2011 1.4

* shape of output fits the adressed field now
* little more docu and error checking

07 Feb 2012 1.5

Added H1 line; fixed bug when asking for a column of indices only

Contact us