function dX = internal_sortBackward(dX, I, dim)
% This function is undocumented and will change in a future release.

%   Copyright 2023-2023 The MathWorks, Inc

dX = iInversePermute(dX, I, dim);
end

%% Helper functions

function A = iInversePermute(B, I, dim)

% Inputs:
% - B: sorted array
% - I: indices of the sorted elements
% - dim: dim along which the sorting is performed
% Output: original array before sorting

needsTranspose = false;
needsReshape = false;
ndim = ndims(B);
szB = size(B);

if dim == 1 && ndim > 2
    % Sorting performed along the 1st dim of a ndarray
    permutedSz = size(B);

    % Reshape B to have the 1st dim as szB(dim). (For example, 2x3x2 -> 2x6)
    B = reshape(B, szB(dim), []);
    I = reshape(I, szB(dim), []);
    needsReshape = true;

elseif dim == 2 && ndim == 2
    % 2D array: sorting performed along the 2nd dim
    B = transpose(B);
    I = transpose(I);
    needsTranspose = true;

elseif dim == 2 && ndim > 2
    % Sorting performed along the 2nd dim of a ndarray
    permVector = [2 1 3:ndim];

    % Permute dims of B (bring the sorted dim to the 1st position)
    B = permute(B, permVector);
    I = permute(I, permVector);
    permutedSz = size(B);

    % Reshape B to have the 2nd dim as szB(2)
    B = reshape(B, szB(2), []);
    I = reshape(I, szB(2), []);
    needsReshape = true;

elseif dim > ndim
    % Degenerate case: no sorting takes place.
    A = B;
    return

elseif dim > 2 && ndim > 2
    % Sorting was performed along a higher dim of a ndarray
    permVector = [dim 1:(dim-1) (dim+1):ndim];

    % Permute dims of B (bring the sorted dim to the 1st position)
    B = permute(B, permVector);
    I = permute(I, permVector);
    permutedSz = size(B);

    % Reshape B to have the dim-th dim as szB(dim)
    B = reshape(B, szB(dim), []);
    I = reshape(I, szB(dim), []);
    needsReshape = true;
end

% Inverse permutation along the 1st dim
A = iInversePermute2dDim1(B, I);

% Permute output to original size.
if needsTranspose
    A = transpose(A);
elseif needsReshape
    A = reshape(A, permutedSz);
    % Permute dims of A to the original order
    A = permute(A, [2:dim 1 (dim+1):ndim]);
end
end

function A = iInversePermute2dDim1(B, I)

% Inputs:
% - B: sorted array
% - I: indices of the sorted elements
% Output: original array before sorting

% Get sizes of B along 1st and 2nd dims
[sz1, sz2] = size(B, [1 2]);
% Indices needed to rearrange the elements of B back to their original
% positions along the 1st dim
idx = 0:sz1:sz1*(sz2-1);
% Indices at which the sorted elements of B should be placed to obtain the
% original order
ii = I + repmat(idx, [sz1 1]);
AA(ii) = B;
A = reshape(AA, [sz1 sz2]);
end