%LSSOL   Convex quadratic programming and linear least-square code LSSOL by
%        Gill et. al.
%        [x,obj,lambda,istate,iter,inform,R,b,kx] = ...
%           lssol(R,b,c,A,x,l,u,tp,msglvl,kx)
%        solves the problem 
%                        minimize     f(x)
%                        subject to   ( )     ( x )    ( )
%                                     (l) =<  (   ) =< (u)
%                                     ( )     ( Ax)    ( )
%        where f(x) is one of the following objective functions:
%         tp = 'fp'   f(x) = none                       
%         tp = 'lp'   f(x) = c'*x                       
%         tp = 'qp1'  f(x) = 0.5*x'*R*x                     R symmetric and psd
%         tp = 'qp2'  f(x) = c'*x + 0.5*x'*R*x              R symmetric and psd
%         tp = 'qp3'  f(x) = 0.5*norm(R(:,kx)*x)^2          R upper-trapezoidal
%         tp = 'qp4'  f(x) = c'*x + 0.5*norm(R(:,kx)*x)^2   R upper-trapezoidal
%         tp = 'ls1'  f(x) = 0.5*norm(b-R*x)^2          
%         tp = 'ls2'  f(x) = c'*x + 0.5*norm(b-R*x)^2   
%         tp = 'ls3'  f(x) = 0.5*norm(b-R(:,kx)*x)^2        R upper-trapezoidal
%         tp = 'ls4'  f(x) = c'*x + 0.5*norm(b-R(:,kx)*x)^2 R upper-trapezoidal
%        
%        On successful termination, x contains the optimal solution, and
%        obj contains the final objective function value. Lambda contains
%        the Lagrange multiplier vector, istate denotes the status of the
%        constraints and iter denotes the number of iterations. Inform
%        contains information about the exit status of LSSOL. Msglvl 
%        determines the amount of output. Msglvl=1 (default) gives one line
%        of output per iteration, msglvl=0 gives no output. Kx determines the
%        column ordering of R for the cases where R is upper-trapezoidal. On
%        exit, R and b are transformed according to the user's guide.
%  
%        This version for Matlab 4.0 dated 19-Apr-1993.

%        M-file written by    Anders Forsgren
%                             Division of Optimization and Systems Theory
%                             Department of Mathematics
%                             Royal Institute of Technology
%                             S-100 44 Stockholm
%                             Sweden
%                             andersf@math.kth.se

function [x,obj,lambda,istate,iter,inform,R,b,kx] = ...
            lssol(R,b,c,A,x,l,u,tp,msglvl,kx)

[m,n] = size(R);
if m == 0
   R = zeros(size(x'));
   b = 0;
   [m,n] = size(R);
end

if nargin < 8
   tp = 'ls1';
end
if nargin < 9
   msglvl = 1;
end
if nargin < 10
   kx = [1:n]';
end

[mA,nA] = size(A);
[lb] = length(b);
[lc] = length(c);
[lx] = length(x);
[ll] = length(l);
[lu] = length(u);

errdim = 0;
tp = lower(tp);
if strcmp(tp,'fp'),
   if ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx),
      errdim = 1;
   end
elseif strcmp(tp,'lp'),
   if (lc > 0 & lc ~= lx ) | ...
   ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx),
      errdim = 1;
   end
elseif strcmp(tp,'qp1'),
   if ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   m ~= n | ...
   n ~= lx,
      errdim = 1;
   end
elseif strcmp(tp,'qp2'),
   if (lc > 0 & lc ~= lx ) | ...
   ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   m ~= n | ...
   n ~= lx,
      errdim = 1;
   end
elseif strcmp(tp,'qp3'),
   if (lc > 0 & lc ~= lx ) | ...
   ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   n ~= lx,
      errdim = 1;
   end
elseif strcmp(tp,'qp4'),
   if (lc > 0 & lc ~= lx ) | ...
   ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   n ~= lx,
      errdim = 1;
   end
elseif strcmp(tp,'ls1'),
   if ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   n ~= lx | ...
   lb ~= m,
      errdim = 1;
   end
elseif strcmp(tp,'ls2'),
   if (lc > 0 & lc ~= lx ) | ...
   ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   n ~= lx | ...
   lb ~= m,
      errdim = 1;
   end
elseif strcmp(tp,'ls3'),
   if ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   n ~= lx | ...
   lb ~= m,
      errdim = 1;
   end
elseif strcmp(tp,'ls4'),
   if (lc > 0 & lc ~= lx ) | ...
   ll ~= lu | ...
   ll ~= mA + lx | ...
   (nA > 0 & nA ~= lx) | ...
   n ~= lx | ...
   lb ~= m,
      errdim = 1;
   end
end

if errdim,
   clear errdim lb m n mA nA lc lx ll lu obj lambda istate iter inform msglvl
   disp('                                                              ')
   disp(' --- Error using LSSOL, incompatible dimensions of input data.')
   disp(' --- LSSOL not executed. Please check below and correct.      ')
   disp('                                                              ')
   whos
else
   [x,obj,lambda,istate,iter,inform,R,b,kx] = ...
       lssolmex(R,b,c,A,x,l,u,tp,msglvl,kx);
end
