function [uk_clipped, clipped] = mpc_clipping(uk, uk1, uoff, Mlim, Mrows, ...
    p, ny, degrees)
% When solution to QP has not been obtained (because specified limit on
% iterations has been reached), clip the uk values to respect speciried
% MV bounds.  Bounds must be obtained from the Mlim array.  See
% mpc_buildmat for its definition.

% Authors:  A. Bemporad, N.L. Ricker, R. Chen
% Copyright 1994-2020 The MathWorks, Inc.

%#codegen

ONE = ones(1,1,'like',uk);
ZERO = zeros(1,1,'like',uk);

% Dimensions
nu = length(uk);
nrows = length(Mrows);
nylim = 2*p*ny;
pnu = p*nu;
nmoves = degrees - ones('int32');  % Total number of du values calculated in QP (isQP is always true here)

% Initialization
uk_clipped = uk;
clipped = false;

% Return if there are no standard constraints
if nrows <= ZERO
    return
end

% Extract any finite bounds on u and du from the Mlim array.  Note that we
% only impose bounds on the first step in the horizon.

umax = inf(nu, 1, 'like', uk);  
umin = -umax;
dumin = umin;
dumax = umax;

for i = 1:nrows
    ix = Mrows(i);      % index of constraint indicates its type
    if (ix > nylim) && (ix <= nylim + nu)
        iu = ix - nylim;
       	umax(iu) = Mlim(i) + uoff(iu);
    elseif (ix > nylim + pnu) && (ix <= nylim + pnu + nu)
        iu = ix - (nylim + pnu);
     	umin(iu) = -Mlim(i) + uoff(iu);
   	elseif (ix > nylim + 2*pnu) && (ix <= nylim + 2*pnu + nu)
       	iu = ix - (nylim + 2*pnu);
       	dumax(iu) = Mlim(i);
    elseif (ix > nylim + 2*pnu + nmoves) && (ix <= nylim + 2*pnu + nmoves + nu)
        iu = ix - (nylim + 2*pnu + nmoves);
       	dumin(iu) = -Mlim(i);
    end
end

% Loop for each MV
for iu = 1:nu
    % First enforce du limits.
    du = uk(iu) - uk1(iu);
    if du > dumax(iu)
        uk_clipped(iu) = uk1(iu) + dumax(iu);
        clipped = true;
    elseif du < dumin(iu)
        uk_clipped(iu) = uk1(iu) + dumin(iu);
        clipped = true;
    end
    % Then enforce u limits, which gives them highest priority if there is
    % a conflict
    if uk_clipped(iu) > umax(iu)
        uk_clipped(iu) = umax(iu);
        clipped = true;
    elseif uk_clipped(iu) < umin(iu)
        uk_clipped(iu) = umin(iu);
        clipped = true;
    end
end
