function B = redistribute(A, destCodistr)
%REDISTRIBUTE Redistribute a codistributed array with another codistributor
%   D2 = REDISTRIBUTE(D1, CODISTR) redistributes a codistributed array D1 to
%   have the distribution scheme CODISTR.
%   
%   Example:
%   spmd
%       N = 1000;
%       M = codistributed(magic(N), codistributor('1d', 2));
%       P = codistributed(pascal(N), codistributor('1d', 1));
%       R = redistribute(P, getCodistributor(M));
%   end
%   
%   See also CODISTRIBUTED, CODISTRIBUTOR/CODISTRIBUTOR.


%   Copyright 2006-2020 The MathWorks, Inc.

narginchk(2, 2);

if ~isa(A, 'codistributed')
    error(message('parallel:distributed:RedistributeFirstInput'))
end

if ~isa(destCodistr, 'AbstractCodistributor')
    error(message('parallel:distributed:RedistributeSecondInput', class( destCodistr )))
end

if istimetable(A)
    % Timetables have a time vector that is not copied via normal indexing.
    % The easiest way to handle this is to convert to a table, do the
    % redistribution, then convert back. (NB tables *do* obey normal
    % indexing rules).
    destCodistr.hVerifySupportsTable();
    tA = timetable2table(A);
    tA = redistribute(tA, destCodistr.hGetNewForSize(size(tA)));
    B = table2timetable(tA); % NB: Don't need to specify time variable as timetable2table always put it first
    return;
end

LP = getLocalPart(A);
codistr = getCodistributor(A);

% Various subsref/subsasgn might remove zero imaginary parts in the
% process. We create needComplexB flag to add zero imaginary parts in the
% end. Even if data gets reshuffled, we will never increase the
% inconsistency between workers regarding complexity.
needComplexB = ~isreal(LP);
   
if istable(A)
    % For tables we also need the global variable names and types so that
    % we can build the right local part.
    tableTemplate = getTableTemplate(A);
    [LP, codistr] = distributedutil.Redistributor.redistribute(codistr, LP, destCodistr, tableTemplate);
else
    [LP, codistr] = distributedutil.Redistributor.redistribute(codistr, LP, destCodistr);
end

if needComplexB && isreal(LP)
    LP = complex(LP);
end

B = codistributed.pDoBuildFromLocalPart(LP, codistr);

