preallocating memory without storing numbers

1 view (last 30 days)
Hi all,
I have several vectors that grow duing a for loop. I know that you should preallocate the size using zeros for speed. My problem is that filling the vectors with zeros interferes with how the elements of the vectors are created; essentially, the vectors have to be empty for it to do what I need.
Is there a way to preallocate memory but have the vectors contain any values/ elements?
Thanks in advance!
  5 Comments
David Goodmanson
David Goodmanson on 8 Jul 2022
Hi Philine,
Just for fun here is a 0x100 empty vector of doubles:
a = find(3<(1:2)')
a = 0×1 empty double column vector
b = repmat(a,1,100)
b = 0×100 empty double matrix
(Not that you could actually use it for anything, since its first dimension is 0).
Philine Baumert
Philine Baumert on 14 Jul 2022
Thanks for your answers so far and please excuse my delayed reply!
It's really tough to show only a small part of what I'm trying to do but I'll give it a shot...
So I have a script with a for e = 1:5 loop and it contains three tasks as functions that again each have a for k = 1:10 loop. Within the task-functions there is another function. It changes n (from the task function) on every iteration of k and e but doesn't start from scratch for each iteration of e but has to continue from where it left off. I tried to give you parts of one of the task-functions and the one changing n.
If I create zero vectors, the functions don't work as intended.
function [RTDensT, AccuracyDensT, newDensT, trialidDensT] = DensTest(Results, e)
try
ntrials = 3;
position = [1 2];
RTDensT = [];
AccuracyDensT = [];
AccuracyDensFac = [];
newDensT = [];
trialidDensT = [];
n = 1.47;
for k=1:ntrials
if e == 1
trialidDens = k;
elseif e > 1
trialidDens = k + e + 1;
AccuracyDensFac = Results(:, 2);
AccuracyDensFac = AccuracyDensFac' ;
end
[newDens] = DensityFactor(n, trialidDens, AccuracyDensFac);
n = newDens;
newDensT((end+1)) = n;
trialidDensT((end+1)) = trialidDens;
end
function [newDens] = DensityFactor(n, trialidDens, AccuracyDensFac)
% Staircase Density
try
if trialidDens < 3
newDens = n;
elseif trialidDens >= 3
if AccuracyDensFac(((end-2):end))==1
newDens = n - 0.05;
elseif AccuracyDensFac(end)==0
newDens = n + 0.02;
end
if newDens < 1.35
newDens = 1.35;
elseif newDens > 1.65
newDens = 1.65;
end
end

Sign in to comment.

Accepted Answer

Jeffrey Clark
Jeffrey Clark on 15 Jul 2022
@Philine Baumert, given that your issue is with code using the end index into arrays which by default won't work correctly with preallocated ones, this has at least two ways to proceed.
  1. Preallocate with zeros or nan as desired, but create variables that are used in place of end and are set to zero/one as appropriate. Just replace end with the appropriate variable name and when indexing to end+1 add a statement to increment the variable after the statement using it.
  2. OR create a class that is a subclass of double (or whatever numeric is appropriate) and overload the method end (see end as Object Index) and use/provide the index into the preallocated arrays of that type as a property of the class used in the overloaded end method. Doing this will work accross function calls and the same class will keep track of the "end" separately for each array. Probably want to have the preallocation of the data space done as part of the class construct call - like:
newDensT = yourClass(1,5000); %preallocate a 1x5000 vector - "end" is set to zero
. . .
newDensT((end+1)) = n; % will use 0 for end the first time and increment by one every time
  2 Comments
Jeffrey Clark
Jeffrey Clark on 15 Jul 2022
@Philine Baumert, note that depending on how your code develops, you will probably also want to overload length, numel and size to use the simulated end (although if the builtins for these call end they may give correct results without overloading - test, test...)
The big thing I didn't mention is that subsasgn must be overloaded to see if the assignment is trying to increase your simulated end as in newDensT((end+1)) = n. The end override method will already have been called to insert the current end in the computed indexs input to subsasgn so just test the appropriate index (row, col, etc) passed into subsasgn against the simulated end and store if greater. Then set the array based upon the varargin or just invoke the builtin subsasgn before exiting to do it:
obj = builtin('subsasgn',obj,s,varargin{:})

Sign in to comment.

More Answers (1)

Jeffrey Clark
Jeffrey Clark on 9 Jul 2022
@Philine Baumert, keeping others in the dark doesn't shed any more light on finding what's hidden. So an answer doesn't seem possible, except maybe this:
myData = zeros(10,20); % dimensions as needed for your expected calculations
isData = false(size(myData)); % critical to keep these dimensions the same
%Do your work here and always set isData true when setting myData
while sum(isData,'all')<numel(myData)/2
i = randi([1 size(myData,1)]);
j = randi([1 size(myData,2)]);
myData(i,j) = randn;
isData(i,j) = true;
end
% Valid results in myData(isData) - note tha regardless of myData being a
% vector, matrix or higher dimension, myData(isData) is a vector. if you
% really need to know the indexs of where the data is (e.g., matrix or
% higher and you really need to know), something like this:
[wasi,wasj] = find(isData);

Tags

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!