Matlab Producing Different Values Running Entire Script VS Single Line Runs

As the title states, I am getting different values from Matlab's length function depending on whether I run the entire script (Using the "Run" button) or just line by line manually. I have no clue why this is occuring but the Matlab functions are not producing correct results themselves when this occurs. I have Matlab on two seperate machines and tried testing the code on both and found the same issue persists. I tried simplifying the code with a very trvial example with the same input structures and the error does not apply to the simpler case. It is just occuring within my main code. For context, I am generating a custom mesh in cylindrical coordinates. The issue occurs on lines 104-105:
stemp = [length(nodesPhis) length(nodesPhiMSim)];
maxNodesPhi = max(length(nodesPhis),length(nodesPhiMSim)); % Finds the max dimension required for the
% phi-component 3D matrix to be populated
If we run the script using the run button, we can see in the variable window that the vector for stemp is [40,53]:
But when I highlight the text to manually run the line, it says [60,53]:
For context, I only define stemp once and in that line 104. Nowhere else is it redefined. Not only this, but even more contradictions come up later in the code from these lines. The code uses the max element of that vector to produce a NAN matrix with one of the dimensions lengths being that max number. This matrix is called "meshPhi", it's size is (x,max(stemp),z) and it is defined as:
meshPhi = NaN(length(nodesR),maxNodesPhi,max(length(nodesZ1),length(nodesZ2))); % Create "empty" phi-mesh to populate
When I run the code with the button, it actually creates the correctly sized meshPhi matrix:
But as can be seen, the meshR and meshZ matrices which are supposed to be the same size, are using 53, and not 60. Those matrices are defined like this on lines 142 and 156:
meshZ = NaN(length(nodesR),maxNodesPhi,max(length(nodesZ1),length(nodesZ2))); % Create "empty" z-mesh to populate
meshR = NaN(length(nodesR),maxNodesPhi,max(length(nodesZ1),length(nodesZ2))); % Create "empty" r-mesh to populate
Exactly the same... so the only thing I can think of is it seems that Matlab is bugged in some way here. Nonetheless, I still wanted to post this question to see if possibly it's not a bug and instead I am potentially missing something or not using an internal function correctly.
Main Code: "TEST_DynCylMesh.m"
Supporting function: "sigdigits.m"

15 Comments

I didn't try to delve into the internals, but
stemp = [length(nodesPhis) length(nodesPhiMSim)];
is very fragile and error-prone code and I'd venture is the root cause of the issues.
length(x) is defined as max(size(x)) and so is dependent upon the size and orientation of the input array; it will return either size(x),1) or size(x),2) depending upon whether x has more rows or columns.
Rewrite your code to use the explicit size() direction you intend before spending any more time scratching your head over this; I strongly suspect the issue will disappear once done. Of course, also be certain to create arrays of the proper orientation when doing so...
If I had a dime for every time I have seen someone say that some code MUST be exposing a bug in MATLAB, I would be wealthy.
If I had to guess what is the problem, even without looking at that lengthy code in any depth, the first thing I would guess is that you did not fully clear your workspace, when you ran the code one line at a time.
Well I didn't say that it must be a bug, it just apeared that way from what I could tell so far. Nonetheless, I stepped away from the computer for a bit and returned with a fresh pair of eyes and found that it was indeed because I miswrote a pi/2 in a predefined linspace isntead of pi, then had reused the same variable name later on in the for loop which was then overriding the value temporarily. So that's a relief! All fixed now
@dpb Thank you for the advice. Those were defined as arrays so that's why I was using length and not size
Well it actually was a bug, but a bug in your code, not MATLAB itself.
" Those were defined as arrays so that's why I was using length and not size..."
That's precisely where length is dangerous; for vectors one dimension is always one; for arrays one can get either row or column size depending...
@dpb Okay yeah I see what you mean now. That is risky. I'll use size() instead from now on for that
length() probably wouldn't make it into the MATLAB stable if it were to be brought up as a new addition now; it existed in first releases as is and so is carried along for compatibility purposes, but really should be avoided owing to the above issues.
If one is extremely careful, one can get by, but it's very possible for an unexpected result to occur when/if data sizes change beyond those that were expected when the code was written. Simply reading an array that now has N+1 variables will return the column size where it is expected to be the row size if there are <=N observations. This case may have been thought to be impossible originally, but things changed.
IMO, the height(), width() functions for tables ought to be extended to accept matrices/arrays as wel(*)l...before they were introduced I built and keep in my Utilities folder nrows(), ncols() as syntax sugar for the size(x,1), size(x,2) idioms; I've suggested those should also be builtins, but has fallen on deaf ears for 30 year or more...
(*) Of course table is constrained to be a 2D object; trying to create an array of tables results in simply appending the table content instead so the English meaning of width and height is maintained whereas for arrays of more than three dimensions there's not such a correlation for the higher dimensions.
I notice that length() actually isn't defined for table objects although one can still use max(size(t)) to get the same end result (although I see no reason why one would want to do that given the problems outlined).
The length function may not have been approved for inclusion in MATLAB in its current form if it had been proposed today, though it might have passed design review if it were limited to returning the number of elements in a vector (as a shortcut for asserting that the input isvector and then returning numel of that vector.)
The height and width functions were enhanced in release R2020b to return the number of rows and columns of an array, respectively, as listed in the Version History sections of those documentation pages.
@dpb length(x) is defined as max(size(x))
Not really.
x=zeros(1,0)
x = 1×0 empty double row vector
length(x)
ans = 0
max(size(x))
ans = 1
"The height and width functions were enhanced in release R2020b..."
Well, I'll be! I've continued to use R2020b to date rather than change horses in midstream of a major data manipulation exercise. Thanks for pointing it out...having my utility functions, I just automagically use them instead so I'd never thought to try it and if I noticed in the release notes, it never made it past the rote usage practice to the conscious level.
I don't recall if any of the musings by Cleve on early versions included anything about why he designed length as did...probably there was a specific use in mind and it seemed like a good idea at the time.
If you want the length of a vector, length does what it says on the tin. When you get to how people actually use it, dragons pop up around every corner.
Adding to the discussion at hand: I maintain that any code you want to use after next week should be in a function. That provides a stable interface that you can document. Of course this is a rule you can break, but only if you follow it first. Problem like this get a lot easier to track down.
I personally compose larger functions from parts (a poor man's package management), so I don't actually need to remember which functions do what. Sometimes I come across a function I wrote years ago. I usually need to wipe some tears and rewrite a lot of code, but only to improve style and performance (or to fix edge cases). The beauty of functions is that it works whether you wrote it terribly or well. And once you update, you shouldn't need to worry about other code depending on it, because every function is a black box to the functions calling it.
@Bruno Luong -- that's the edge case, yes.
The doc actually reads as " For arrays with more dimensions, the length is max(size(X)). The length of an empty array is zero." I did leave off the for zero-length arrays part, yes, since they weren't pertinent in this particular thread.
So strictly in compliance, the form would be max(size((x))*~isempty(x)
x=zeros(1,0);
length(x)
ans = 0
max(size(x))*~isempty(x)
ans = 0
@John, while you've probably lost interest long ere now, with the update that height and width now operate on arrays as well, I'll change my advice to recommend using them instead.

Sign in to comment.

Answers (0)

Products

Release

R2023a

Asked:

on 18 Jun 2023

Edited:

dpb
on 21 Jun 2023

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!