4

If we write, for example:

x = int8.empty(0,5)

whos x outputs:

% Name    Size    Bytes    Class    Attributes
% x       0x5     0        int8     

Thus, we obtain a 0x5 empty array of class int8.

What is the purpose of preallocating an empty array containing a non-null dimension if its memory size is 0 bytes ?

In which case

x = int8.empty(0,5)

is more useful than

x = int8.empty(0,0)

Does int8.empty(0,5) still preallocate 5 "slots" of memory ?

obchardon
  • 10,614
  • 1
  • 17
  • 33
  • Not that I downvoted, but [Why isn't providing feedback mandatory on downvotes, and why are ideas suggesting such negatively received?](https://meta.stackoverflow.com/q/357436/5211833). Also no-one will be pinged by that message, thus unless that specific person comes back, we can only guess as to why that person downvoted you. – Adriaan Oct 14 '20 at 10:34
  • It may be just a residue of the implementation. You either allow it, or add checks to impede it (`assert(all(dim!=0))` kind of thing) and they may have decided to go just allow it. Ultimately the dimensions and dimension sizes are just a member of the "matlab matrix" class, the data is always a 1D array. – Ander Biguri Oct 14 '20 at 10:43
  • @AnderBiguri thank you for your feedback, it was also my guess. But I'm still confused with the [`empty`](https://mathworks.com/help/matlab/ref/empty.html) documentation. In this doc we can see a lot of example where `SomeClass.empty(0,n)` (with `n>1`) are used, it looks like it has been implemented on purpose. – obchardon Oct 14 '20 at 10:52
  • ah, I didnt even see that you where doing `empty` sorry. Well, yeah, an `empty` array must have a dimension that is zero, otherwise its not empty. – Ander Biguri Oct 14 '20 at 12:40
  • @AnderBiguri I think the question is that why such an array is allowed to have dimensions that are greater than 0. – rahnema1 Oct 14 '20 at 12:52
  • @rahnema1 yes exactly, if `int8.empty(0,5)` does not preallocate some "slot" of memory, then why not using `int8.empty(0)` instead ? – obchardon Oct 14 '20 at 12:59
  • or even `int8.empty(0,0)`. – rahnema1 Oct 14 '20 at 13:00
  • 1
    I suspect to be able to give it as input to codes, perhaps for testing, or just to have the flexibility. They may be empty, but they still follow operator rules (multiplication, logic operations, concatenation, etc). e.g `ones(1,5)*double.empty(5,0)` is valid, but `ones(1,5)*double.empty(1,0)` is not. – Ander Biguri Oct 14 '20 at 13:07
  • 2
    Considering this is OOP type of thing, the basic `matlabtype.empty` may not be of interest, but with custom classes, there is a lot of information aside from its size that an `myClass.empty` can contain and share. Not an expert and have never used it, so I won't answer the question – Ander Biguri Oct 14 '20 at 13:25
  • 1
    It is also allowed to iterate over empty arrays: `for i = zeros(0,5)`. – rahnema1 Oct 14 '20 at 13:27
  • 1
    "Does int8.empty(0,5) still preallocate 5 "slots" of memory ?" - To be formal: No. (For primitive types.) Matlab allocates memory for the total number of *elements* in the array, which is equal to the product of all dimensions. 0 x 5 = 0 elements, so it allocates 0 bytes of raw data. (Plus the normal per-array "bookkeeping" overhead stuff.) – Andrew Janke Oct 15 '20 at 17:17

2 Answers2

4

The simplest answer I can think of is continuity - so that my code doesn't have to write a special case if something turns out to need zero rows or columns. Consider this slightly silly function:

function out = getAllRowsGt5(someMatrix)
rowIdxs = find(sum(someMatrix, 2) > 5);
out = zeros(numel(rowIdxs), size(someMatrix, 2));
for idx = 1:numel(rowIdxs)
    out(idx,:) = someMatrix(rowIdxs(idx), :);
end
end

Sure, there are simpler ways of implementing that in MATLAB. But the point is that I want to preallocate the result based on the values in the input. This code has well-defined post-conditions:

size(out, 2) == size(someMatrix, 2)

and it doesn't have to special-case the situation where nothing matched my condition. Neither of those would be true if there was a limitation on the shape of empty arrays allowed by MATLAB.

Edric
  • 23,676
  • 2
  • 38
  • 40
  • While this is a good example for using `numel` to get the size of an (empty?) array I think it doesn't answer the question. Suppose that `find` returns empty arrays of size `[3 ,2 ,0]` or `[0 1 1]` or `[0 0 0]` . In all of the cases `numel` returns `0`. Anyway I expect there are more theoretical instead of practical reasons behind empty arrays . For example it may be attempt of MATLAB to implement [`nullable types`](https://en.wikipedia.org/wiki/Nullable_type). – rahnema1 Oct 15 '20 at 02:22
  • 1
    I don't understand your point - `find` always returns a vector of linear indices - no element will ever be `0`. I suppose the nearest I've got to a "theoretical" argument is the continuity argument - it stops empty dimensions being a special case. As for nullable types - in certain circumstances MATLAB treats `[]` as "null", but many types also support a non-empty `missing` value that can be part of an array - a generalisation of `NaN`. See https://www.mathworks.com/help/matlab/ref/missing.html and also `ismissing`, `rmmissing`. – Edric Oct 15 '20 at 08:31
  • You are right. `find` always returns a vector. My point and I think the concerns of the question is related to that why for example `find` may return a `[n by 0]` or `[0 by n]` vector instead of returning a `[0 by 0]` vector. What are the practical benefits and theoretical backends of empty arrays of dimensions `[3 by 2 by 0]` or `[0 by 1]`? Why all of dimensions aren't `0`? – rahnema1 Oct 15 '20 at 08:54
  • 1
    `0 x 0` is not considered as a vector in MATLAB - vectors have exactly one unity dimension. (And actually `find` doesn't _always_ return a vector - unfortunately, there's a wrinkle with `find` which means that when you call it on the scalar `0`, it doesn't know whether it should return an empty row or an empty column - so it returns `[]`). I attempted to show the practical benefits of supporting `0 x N` in my example - if only `0 x 0` empties were allowed, I'd have to add special-case code when `numel(rowIdxs) == 0`. – Edric Oct 15 '20 at 13:33
  • Isn't it "vectors have exactly one NON-unity" dimension? E.g. an array of size [1 1 1 1 8 1] is a vector. – Andrew Janke Oct 15 '20 at 17:13
  • 1
    I've run in to a practical use case for 0-by-n vectors: with Matlab's new declarative property and argument constraints, you can say things like "x must be an N-by-1" or "z must b n-by-3" by declaring it as `(:,1)` or `(:,3)`. This allows you to represent the empty set in a conformant way. – Andrew Janke Oct 15 '20 at 17:14
  • @AndrewJanke Good point! I have also some examples in mind. Could you post your comment as an answer? But note that as far as I know empty arrays are dated before the new argument checking syntax. – rahnema1 Oct 16 '20 at 01:46
  • Thanks! Posted that with some additional commentary as an answer. And yes, empty arrays predate the new argument checking syntax by something like three decades. :) – Andrew Janke Oct 16 '20 at 02:48
  • As far as MATLAB is concerned, vectors (as defined by `isvector`) have a maximum dimensionality of 2, and have _at least_ one unity dimension. I.e. `isvector(42) == true`, but `isvector(ones(1,1,2)) == false`. Note also that arrays in MATLAB have at least 2 dimensions, but trailing unity dimensions beyond the second are (generally) disregarded. You can treat any array in MATLAB as having any number of dimensions, but the "natural" dimensionality trims the trailing unity dimensions. I.e. `size(42, 17) == 1`. – Edric Oct 16 '20 at 10:19
4

I've run in to a practical use case for 0-by-n vectors: with Matlab's new declarative property and argument constraints, you can say things like "x must be an N-by-1" or "z must b n-by-3" by declaring it as (:,1) or (:,3). This allows you to represent the empty set in a conformant way.

There are also formal reasons for doing so: A function or operation may be defined in terms of the dimensionality of its inputs, such as "takes an m-by-n array and returns a k-by-n array where k = somefunction(m or its values)", and in degenerate cases where k turns out to be zero, an empty array with some nonzero dimensions allows operations like this that still strictly adhere to their contracts.

In practical terms, for basic operations like concatenation and such, all empty arrays are usually interchangeable, and will usually Just Work or at most produce a warning.

Andrew Janke
  • 23,508
  • 5
  • 56
  • 85
  • 1
    Beware, concatenation in the presence of empties is... weirder than you might hope, for hysterical reasons. Compare `horzcat(zeros(0,1), zeros(1,0))` with `cat(2, zeros(0,1), zeros(1,0))` for example. Generally, the `0x0` empty is the Most Special Empty though, and acts as a concatenation wildcard (as well as the deleting-assignment operator - but only if you don't name it). – Edric Oct 16 '20 at 10:28