Today's post will take us on an historical tour of the function zeros, and pertains, in various ways, to the related functions ones, eye, false, true, rand, randn, and complex.
You might think "How can a function like zeros need to evolve at all?" - but you will see some of the MATLAB changes that lead to the evolution.
In Cleve's original Fortran MATLAB, there was no zeros function. However, the function ones had the following help entry:
ONES All ones. ONES(N) is an N by N matrix of ones. ONES(M,N) is an M by N matrix of ones. ONES(A) is the same size as A and all ones.
When I first started using MATLAB in 1987(version 3.05a), the behavior for the function zeros matched this ones design, with the obvious difference being the matrix had values of 0 instead of 1 for all of its entries.
Notice what this design means. I always get an array the same size as A unless A is a scalar. And then we get something with size A by A. This means that if we want to ever get a scalar value for zeros, we must constantly program defensively and ask if A is a scalar, and then create zeros(1), else create zeros(A). Constantly. This was a source of both confusion and bugs in code where people didn't recognize the discontinuity in behavior when they were programming.
To alleviate this nuisance, in MATLAB Version 4, we no longer used the syntax zeros(A) but instead expected the inputs to be non-negative integers. MATLAB still only had 2-dimensional double arrays (with an attribute describing when to interpret the values as characters). With this design, there was no more need for such defensive programming.
Once we introduced higher dimensional arrays in MATLAB (version 5), we changed the input syntax for zeros to allow 2 scalar non-negative integer inputs OR a vector of such values for N-Dimensional arrays. While it was nice to be able to create higher dimensional arrays this way, it was tricky to create them for non-double datatypes, another new feature in that release of MATLAB.
The most common way to generate an array of zeros of another type was to first create the correctly sized double array and then convert it to, let's say uint8. This was inefficient, first creating an array using 8 times more memory than necessary, and then converting it to the uint8 array, with its smaller datatype.
Of course there were ways around this too. You could create a scalar zero of the right datatype, e.g., and then set that to be the final element in a newly created array, like this for your 4-D array:
B(m,n,p,q) = uint8(zeros(1));
Effective, but perhaps a bit cryptic.
In MATLAB 7, we introduced another new syntax for zeros and companions, allowing you to specify the datatype of the output, provided that it was one of the built-in datatypes. Here's a snippet of the relevant information.
X = zeros(..., classname) classname restricted to built in types: 'double', 'single', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', or 'uint64'
This was definitely more memory efficient than creating an array of doubles and then coverting them. And less mysterious than setting the end element of a new array to a zero of the right type.
There was a remaining limitation however. It was still cumbersome to create an array of zeros of a user-defined datatype, including classes that shipped as part of our products.
In addition to creating zero-arrays in all the ways possible since MATLAB Version 4, you can now create an array of zeros to be like another array, saving you the hassle of finding out that array's size and type and passing that information along. And it also allows you to create arrays of any datatype, built-in or user-defined. How do you do this? Here's one of the possible syntax choices.
X = zeros(sz1,...,szN,'like',p)
Have you been able to take advantage of some of these changes over time? Did you know about them? I'd love to hear your thoughts here.