function x = eml_fftshift(x,dim)
%MATLAB Code Generation Private Function

%   FFTSHIFT of X along dimension DIM.  DIM is not validated.

%   Copyright 2006-2023 The MathWorks, Inc.
%#codegen

coder.internal.allowHalfInputs;
eml_invariant(nargin == 2, ...
    'MATLAB:minrhs');
coder.internal.prefer_const(dim);
if dim > ndims(x)
    return
end
vlen = size(x,dim);
if vlen <= 1
    return
end
vlend2 = coder.internal.indexDivide(vlen,2);
if coder.gpu.internal.isGpuEnabled && ~coder.internal.isConstantFolding
    vstride = ones(coder.internal.indexIntClass);
    npages = ones(coder.internal.indexIntClass);
    
    coder.gpu.nokernel;
    for i = 1:dim-1
        vstride = coder.internal.indexTimes(vstride, size(x,i));
    end
    
    coder.gpu.nokernel;
    for i = dim+1:ndims(x)
        npages = coder.internal.indexTimes(npages, size(x,i));
    end
else
    vstride = coder.internal.prodsize(x,'below',dim);
    npages = coder.internal.prodsize(x,'above',dim);
end
vspread = coder.internal.indexTimes(coder.internal.indexMinus(vlen,1),vstride);
midoffset = coder.internal.indexTimes(vlend2,vstride);

if coder.gpu.internal.isGpuEnabled && ~coder.internal.isConstantFolding
    if coder.internal.indexTimes(vlend2,2) == vlen
        zero_index = zeros(coder.internal.indexIntClass);
        coder.gpu.kernel;
        for i = 1:npages
            coder.gpu.kernel;
            for j = 1:vstride
                coder.gpu.kernel;
                for k = 1:vlend2
                    i1 = coder.internal.indexPlus(zero_index, (i-1) * (vspread + vstride));
                    i1_s = coder.internal.indexPlus(i1,j);
                    ia_start = i1_s;
                    ib_start = coder.internal.indexPlus(i1_s,midoffset);
                    ia = coder.internal.indexPlus(ia_start, (k-1) * vstride);
                    ib = coder.internal.indexPlus(ib_start, (k-1) * vstride);
                    tmp = x(ia);
                    x(ia) = x(ib);
                    x(ib) = tmp;
                end
            end
        end
    else
        zero_index = zeros(coder.internal.indexIntClass);   
        size_of_the_chunk1 = vlend2+1;
        start_index1 =  ones(coder.internal.indexIntClass);
        size_of_the_chunk2 = vlend2;
        start_index2 = coder.internal.indexPlus(vlend2, 2); 
        
        size_of_the_chunk3 = coder.internal.indexPlus(zero_index, vlen);
        start_index3 =  coder.internal.indexPlus(zero_index, 1);
                

        %reverse subarrays
        coder.gpu.kernel;
        for i = 1:npages
            coder.gpu.kernel;
            for j = 1:vstride
              
                coder.gpu.kernel;
                for k = 1:coder.internal.indexDivide(size_of_the_chunk1, 2)
                    
                    ia_start1 = coder.internal.indexPlus(...
                        coder.internal.indexPlus(zero_index, ((i-1) * (vspread + vstride)) + j),...
                        (start_index1 - 1) * vstride);
                    
                    ib_start1 = coder.internal.indexPlus(ia_start1, (size_of_the_chunk1-1) * vstride);
                    ia1 = coder.internal.indexPlus(ia_start1, (k-1) * vstride);
                    ib1 = coder.internal.indexMinus(ib_start1, (k-1) * vstride);
                    
                    tmp = x(ia1);
                    x(ia1) = x(ib1);
                    x(ib1) = tmp;
                    
                    
                    
                    ia_start2 = coder.internal.indexPlus(...
                        coder.internal.indexPlus(zero_index, ((i-1) * (vspread + vstride)) + j),...
                        (start_index2 - 1) * vstride);
                    ib_start2 = coder.internal.indexPlus(ia_start2, (size_of_the_chunk2 - 1) * vstride);
                    ia2 = coder.internal.indexPlus(ia_start2, (k-1) * vstride);
                    ib2 = coder.internal.indexMinus(ib_start2, (k-1) * vstride);
                    tmp = x(ia2);
                    x(ia2) = x(ib2);
                    x(ib2) = tmp;
                    
                    
                end
            end
        end
        
        %reverse entire array
        coder.gpu.kernel;
        for i = 1:npages
            coder.gpu.kernel;
            for j = 1:vstride   
          %%
                              
                coder.gpu.kernel;
                for k = 1:coder.internal.indexDivide(size_of_the_chunk3, 2)
                    ia_start3 = coder.internal.indexPlus( coder.internal.indexPlus( zero_index, ((i-1) * (vspread + vstride)) + j), (start_index3 - 1) * vstride);
                    ib_start3 = coder.internal.indexPlus(ia_start3, (size_of_the_chunk3 - 1) * vstride);
                    ia3 = coder.internal.indexPlus(ia_start3, (k-1) * vstride);
                    ib3 = coder.internal.indexMinus(ib_start3, (k-1) * vstride);
                    tmp = x(ia3);
                    x(ia3) = x(ib3);
                    x(ib3) = tmp;
                end
            end
        end
    end
else
    if coder.internal.indexTimes(vlend2,2) == vlen
        % Handle even length dimension.
        i2 = zeros(coder.internal.indexIntClass);
        for i = 1:npages
            i1 = i2;
            i2 = coder.internal.indexPlus(i2,vspread);
            for j = 1:vstride
                i1 = coder.internal.indexPlus(i1,1);
                i2 = coder.internal.indexPlus(i2,1);
                % Shift x(i1:vstride:i2)
                ia = i1;
                ib = coder.internal.indexPlus(i1,midoffset);
                for k = 1:vlend2
                    tmp = x(ia);
                    x(ia) = x(ib);
                    x(ib) = tmp;
                    ia = coder.internal.indexPlus(ia,vstride);
                    ib = coder.internal.indexPlus(ib,vstride);
                end
            end
        end
    else
        % Handle odd length dimension.
        i2 = zeros(coder.internal.indexIntClass);
        for i = 1:npages
            i1 = i2;
            i2 = coder.internal.indexPlus(i2,vspread);
            for j = 1:vstride
                i1 = coder.internal.indexPlus(i1,1);
                i2 = coder.internal.indexPlus(i2,1);
                % Shift x(i1:vstride:i2))
                ia = i1;
                ib = coder.internal.indexPlus(i1,midoffset);
                xtmp = x(ib);
                for k = 1:vlend2
                    ic = coder.internal.indexPlus(ib,vstride);
                    x(ib) = x(ia);
                    x(ia) = x(ic);
                    ia = coder.internal.indexPlus(ia,vstride);
                    ib = ic;
                end
                x(ib) = xtmp;
            end
        end
    end
end

% LocalWords:  subarrays vstride
