bugGNU Octave - Bugs: bug #45389, nd-array indexing with fewer...

 
 

bug #45389: nd-array indexing with fewer subscripts than dimensions

Submitter:  Amro <amro_octave>
Submitted:  Wed 24 Jun 2015 08:22:20 AM UTC
   
 
Category:  Interpreter Severity:  2 - Minor
Priority:  3 - Low Item Group:  Matlab Compatibility
Status:  Confirmed Assigned to:  None
Originator Name:  Open/Closed:  * Open
Release:  * dev Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Sat 25 Jul 2015 03:13:02 AM UTC, comment #5: 

Thanks Nick for the clearer explanation.

I have discussed this in a MATLAB/Octave chat room, and someone pointed out that the reshaping behavior was mentioned a few years ago in an official blog post:

http://blogs.mathworks.com/loren/2006/08/09/essence-of-indexing/

See the the bullet point "Indexing with fewer indices than dimensions". Unfortunately only the RHS case was considered, and no mention of what the expected outcome is for LHS expressions, especially when growing the array...

Another post where this was shown:

http://blogs.mathworks.com/loren/2006/11/10/all-about-the-colon-operator/#6

(see the section "Collapsing Trailing Dimensions").

Amro <amro_octave>
Sat 25 Jul 2015 12:02:42 AM UTC, comment #4: 


Just want to follow up on comment #2. Matlab's behaviour is 'correct and consistent' with how they've defined indexing. ML isn't making any unclear assumptions as Rik implied in comment #1, it should most definitely accept x(3,1)==4, not throw an error. Yes, it can be avoided as it's a sloppy way to resize an array, but Octave should follow suit, as it shows Octave is doing something fundamentally different which may lead to other inconsistencies.

Much of Comment #2 has it right, but spelled out in detail it's a collision of expansion and concatenation precedence in Octave:

The expansion rule is simple enough - if you specify all indices, and one is larger than the size in that dimension, it errors out if you're asking it to return the value, but expands the array if you're assigning a value. 

The index-concatenation rule is also straightforward - if you ask for a value, but specify fewer indices than dimensions, the array is concatenated on the last specified dimension. THEN, any other operations are performed on that reshaped array, the outcome of which is then 'reshaped' and returned back in its original form.

When the two collide it appears tricky, but the index-cocatenation SHOULD get done first. I suspect Octave does not do this, and that's the cause of the non-compatibility. If you do it first, then, whether or not any expansion should produce an output or an error is very straightforward.

In short, you can't expand on any concatenated dimension, because it doesn't know which of the concatenated dimensions you actually wanted to expand when it tries to returns the original shape.

Stepping through the previously mentioned operations:


for ML:

x = ones(2,2,2);  #3D array

x(1,3) = 5 # array is concatentad into x(:,:) a 2x4 array, then element (1,3) in            # that array is set to 5, and it's returend in 2x2x2 form. equiv. to
           # x(1,1,2)=5.

x(3,1) = 7 # again, first made into a 2x4 array, then the x(3,1) is applied
           # to that array. 3>2, so it does an array expansion. becomes 3x4.
           # un-concatenates dims 2 and 3 and returns 3x2x2. same as x(3,1,1)=7

x = ones(2,2,2); #3D array
x(9) = 9   # error. x(:) is a nx1 array. expanding on a concatenated dimension
           # doesn't tell you which dimension was supposed to get bigger

x(1,9) = 9 # again, x(:,:) is a 2x4 array. it doesn't know where to put the 9th
           # element.

x(9,9) = 9 # same problem.

x(3,1,1) = 7 # works because there is no concatenation to cause confusion. any dimension can exceed size(x)(dim).


can give another example to highlight the error in Octave:


x = ones(2,2,2,2); #4D array

x(2,3,1) = 4  # x(:,:,:) is a 2x2x4 array, only concatenated on dims 3 and 4.
              # ML is perfectly happy doing expansions on dims 1 or 2

answer in ML:

x(2,3,1)=4

x(:,:,1,1) =
     1     1     0
     1     1     4

x(:,:,2,1) =
     1     1     0
     1     1     0

x(:,:,1,2) =
     1     1     0
     1     1     0

x(:,:,2,2) =
     1     1     0
     1     1     0

Octave gives an ambiguity error and it shouldn't.


I don't know how the code works for the resizing, but I suspect it is rule-checking based on x and not the concatenated x.  hopefully that's not too onerous a fix.

Nicholas Jankowski <nrjank>
Group Member
Wed 24 Jun 2015 05:41:23 PM UTC, comment #3: 

I marked the bug as confirmed, since it definitely is a Matlab Incompatibility.  But I also lowered the priority and severity of the bug since there are easy workarounds.

Rik <rik5>
Group administrator
Wed 24 Jun 2015 05:03:20 PM UTC, comment #2: 

Thank you for the response Rik.

I filed this as a possible MATLAB compatibility issue. I admit it's an edge case, but I only stumbled across it by mistake. I assure you I don't usually write code that bad :)

As for trying to explain the MATLAB behavior, it seems to me there is some logic behind it. Consider this:


>> x=ones(2,2,2);
>> x(:,:)


it effectively reflows the array into a 2-by-(2*2) matrix, similar to doing "reshape".

I think my previous example is interpreted in a similar way, where "x(3,1)" implies reshaping into a 2D matrix, and then indexing into that result. In this case the array is grown in size since we're indexing out of bound.

In the second example with "x(1,9)", MATLAB threw an error because it is not clear which original dimension it should grow (2nd or 3rd?), at least that's the way I explain it...

Anyway, as you said, this can be easily avoided by writing correct and clear code in the first place :) I just wanted to document the difference.

Amro <amro_octave>
Wed 24 Jun 2015 04:22:29 PM UTC, comment #1: 

Try


x(3,1,1) = 7


and the example works.  I think Octave is accurate to throw an error since it isn't clear with just x(3,1) whether you meant to index x(3,1,1) or x(3,1,2).

Matlab makes the assumption that you meant x(3,1,*1*), but not consistently which makes the behavior even worse.  I agree that x(1,9) would seem to imply x(1,9,1) in Matlab but this fails.  Rather than rely on weirdness in Matlab, I would just re-code the m-file to be clear about what is desired.  The re-coded version will work in Matlab or Octave.

Rik <rik5>
Group administrator
Wed 24 Jun 2015 08:22:20 AM UTC, original submission:  

Consider the example below.

First we run it in MATLAB R2015a:


>> x=ones(2,2,2)
x(:,:,1) =
     1     1
     1     1
x(:,:,2) =
     1     1
     1     1

>> x(1,3)=5
x(:,:,1) =
     1     1
     1     1
x(:,:,2) =
     5     1
     1     1

>> x(3,1)=7
x(:,:,1) =
     1     1
     1     1
     7     0
x(:,:,2) =
     5     1
     1     1
     0     0


Next we try it in Octave 4.0.0:


> x=ones(2,2,2)
x =

ans(:,:,1) =

   1   1
   1   1

ans(:,:,2) =

   1   1
   1   1

>> x(1,3)=5
x =

ans(:,:,1) =

   1   1
   1   1

ans(:,:,2) =

   5   1
   1   1

>> x(3,1)=7
error: Invalid resizing operation or ambiguous assignment to an out-of-bounds array element





What's interesting is that on other cases, both MATLAB and Octave throw an error:


>> x=ones(2,2,2);
>> x(9)=9
Attempt to grow array  along ambiguous dimension.
>> x(1,9)=9
Attempt to grow array  along ambiguous dimension.
>> x(9,9)=9
Attempt to grow array  along ambiguous dimension.



>> x=ones(2,2,2);
>> x(9)=9
error: Invalid resizing operation or ambiguous assignment to an out-of-bounds array element
>> x(1,9)=9
error: Invalid resizing operation or ambiguous assignment to an out-of-bounds array element
>> x(9,1)=9
error: Invalid resizing operation or ambiguous assignment to an out-of-bounds array element


Amro <amro_octave>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mmuetzel (Updated the item)
  • -email is unavailable- added by nrjank (Posted a comment)
  • -email is unavailable- added by jwe (Updated the item)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by amro_octave (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 5 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-12-02 mmuetzel Release4.0.0 dev
    2015-06-24 jwe Summarynd-array indexing with less subscripts than dimensions nd-array indexing with fewer subscripts than dimensions
    2015-06-24 rik5 Severity3 - Normal 2 - Minor
        Priority5 - Normal 3 - Low
        StatusNone Confirmed

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code