function output = callsdpt34(interfacedata)

% Retrieve needed data
options = interfacedata.options;
F_struc = interfacedata.F_struc;
c       = interfacedata.c;
K       = interfacedata.K;
x0      = interfacedata.x0;
ub      = interfacedata.ub;
lb      = interfacedata.lb;

% Bounded variables converted to constraints
if ~isempty(ub)
    [F_struc,K] = addbounds(F_struc,K,ub,lb);
end

if any(K.m > 0)
    % Messy to keep track of
    options.sdpt3.smallblkdim = 0;
end

if ~isempty(interfacedata.lowrankdetails)
    options.sdpt3.smallblkdim = 1;
end

if isempty(K.schur_funs)
    % Simple...
    [blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,options.sdpt3.smallblkdim);
else
    % A bit messy if we have a Schur compiler (i.e. STRUL)
    % SDPT3 reorders SDP constraints in order to put many small ones in a
    % common block. Hence, it might happen that it mixes up SDP constraints
    % with Schur compilers and those without. At the moment, we take a
    % conservative approach. If all SDP constraints have a Schur compiler,
    % we allow blocking. If not, we don't. This way our code will work    
     if ~any(cellfun(@isempty,K.schur_funs))
         % All have Schur functions
         [blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,options.sdpt3.smallblkdim);        
     else
         % Messy case, don't allow blocking for now     
         options.sdpt3.smallblkdim = 1;
         [blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,options.sdpt3.smallblkdim);        
     end
end
options.sdpt3.printyes=double(options.verbose);
options.sdpt3.expon=options.sdpt3.expon(1);

% Setup the logarithmic barrier cost. We exploit the fact that we know that
% the only logaritmic cost is in the last SDP constraint
if abs(K.m) > 0
    lpLogsStart = 1;
    for i = 1:size(blk,1)
        if isequal(blk{i,1},'l')
            options.sdpt3.parbarrier{i,1} = zeros(1,blk{i,2});
        elseif isequal(blk{i,1},'u')
            lpLogsStart = 2;
            options.sdpt3.parbarrier{i,1} = zeros(1,blk{i,2});
        else
            options.sdpt3.parbarrier{i,1} = 0*blk{i,2};
        end
    end
    n_sdp_logs = nnz(K.m > 1);
    n_lp_logs  = nnz(K.m == 1);
    if n_lp_logs>0
        lp_count = n_lp_logs;
    end
    if n_sdp_logs>0
        sdp_count = n_sdp_logs;
    end  
    for i = 1:length(K.m)
        if K.m(i) == 1
            % We placed it in the linear cone
            options.sdpt3.parbarrier{lpLogsStart,1}(end-lp_count+1) = -K.maxdetgain(i);
            lp_count = lp_count-1;
        elseif K.m(i) > 1
            % We placed it in the SDP cone
            options.sdpt3.parbarrier{end-sdp_count+1,1} = -K.maxdetgain(i);
            sdp_count = sdp_count-1;
        end
    end
    %options.saveduals = 0;
end

% Setup structures for user-defined Schur compilers
if isfield(K,'schur_funs')
    top = 1;
    if ~isempty(K.schur_funs)
        if K.f>0
            options.sdpt3.schurfun{top} = '';
            options.sdpt3.schurfun_par{top,1} = [];
            top = top+1;
        end
        if K.l > 0
            options.sdpt3.schurfun{top} = '';
            options.sdpt3.schurfun_par{top,1} = [];
            top = top+1;
        end
        if K.q > 0
            options.sdpt3.schurfun{top} = '';
            options.sdpt3.schurfun_par{top,1} = [];
            top = top+1;
        end
        if 0
            for i = 1:length(K.s)
                if ~isempty(K.schur_funs{i})
                    options.sdpt3.schurfun{top} = 'schurgateway';
                    S = createSchurFun(options,K,interfacedata,i);
                    options.sdpt3.schurfun_par{top,1} = S;
                      V = {S.extra,S.data{:}};
                      feval(S.fun,[],[],V{:});
                else
                    options.sdpt3.schurfun{top} = '';
                    options.sdpt3.schurfun_par{top,1} = [];
                end
                top = top+1;
            end
        else
            iSDP = 1;
            while top <= size(blk,1)
                for j = 1:length(blk{top,2})
                    i = oldKs(iSDP);iSDP = iSDP + 1;
                    if ~isempty(K.schur_funs{i})
                        Sname = 'schurgateway';
                     %   options.sdpt3.schurfun{top} = 'schurgateway';
                        S = createSchurFun(options,K,interfacedata,i);
                        S.j = j;
                        S.blk = blk(top,2);
                        options.sdpt3.schurfun_par{top,j} = S;
                    else
                        Sname = '';
                       % options.sdpt3.schurfun{top} = '';
                        options.sdpt3.schurfun_par{top,1} = [];
                    end
                   
                end
                options.sdpt3.schurfun{top} = Sname;                
                top = top+1;                 
            end
        end
        
    end
end

if options.savedebug
    ops = options.sdpt3;
    save sdpt3debug blk A C b ops x0 -v6
end

if options.showprogress;showprogress(['Calling ' interfacedata.solver.tag],options.showprogress);end
solvertime = clock;
if options.verbose==0 % SDPT3 does not run silent despite printyes=0!
   evalc('[obj,X,y,Z,info,runhist] =  sdpt3(blk,A,C,b,options.sdpt3,[],x0,[]);');
else
    [obj,X,y,Z,info,runhist] =  sdpt3(blk,A,C,b,options.sdpt3,[],x0,[]);            
end

% Create YALMIP dual variable and slack
Dual = [];
Slack = [];
top = 1;
if K.f>0
    Dual = [Dual;X{top}(:)];
    Slack = [Slack;Z{top}(:)];
    top = top+1;
end
if K.l>0
    Dual = [Dual;X{top}(:)];
    Slack = [Slack;Z{top}(:)];
    top = top + 1;
end
if K.q(1)>0
    Dual = [Dual;X{top}(:)];
    Slack = [Slack;Z{top}(:)];
    top = top + 1;
end
if K.s(1)>0  
    % Messy format in SDPT3 to block and sort small SDPs
    u = blk(:,1);
    u = find([u{:}]=='s');
    s = 1;
    for top = u
        ns = blk(top,2);ns = ns{1};
        k = 1;
        for i = 1:length(ns)
            Xi{oldKs(s)} = X{top}(k:k+ns(i)-1,k:k+ns(i)-1);
            Zi{oldKs(s)} = Z{top}(k:k+ns(i)-1,k:k+ns(i)-1);
            s = s + 1;                 
            k = k+ns(i);
        end
    end 
    for i = 1:length(Xi)
        Dual = [Dual;Xi{i}(:)];     
        Slack = [Slack;Zi{i}(:)];     
    end
end

if any(K.m > 0)
   % Dual = [];
end

solvertime = etime(clock,solvertime);
Primal = -y;  % Primal variable in YALMIP

% Convert error code
switch info.termcode
    case 0
        problem = 0; % No problems detected
    case {-1,-5,-9} 
        problem = 5; % Lack of progress
    case {-2,-3,-4,-7}
        problem = 4; % Numerical problems
    case -6
        problem = 3; % Maximum iterations exceeded
    case -10
        problem = 7; % YALMIP sent incorrect input to solver
    case 1
        problem = 2; % Dual feasibility
    case 2
        problem = 1; % Primal infeasibility 
    otherwise
        problem = -1; % Unknown error
end
infostr = yalmiperror(problem,interfacedata.solver.tag);

if options.savesolveroutput
    solveroutput.obj = obj;
    solveroutput.X = X;
    solveroutput.y = y;
    solveroutput.Z = Z;
    solveroutput.info = info;
    solveroutput.runhist = runhist;
 else
    solveroutput = [];
end

if options.savesolverinput
    solverinput.blk = blk;
    solverinput.A   = A;
    solverinput.C   = C;
    solverinput.b   = b;
    solverinput.X0   = [];
    solverinput.y0   = x0;
    solverinput.Z0   = [];
    solverinput.options   = options.sdpt3;
else
    solverinput = [];
end

% Standard interface 
output.Primal      = Primal;
output.Dual        = Dual;
output.Slack       = Slack;
output.problem     = problem;
output.infostr     = infostr;
output.solverinput = solverinput;
output.solveroutput= solveroutput;
output.solvertime  = solvertime;

function [F_struc,K] = deblock(F_struc,K);
X = any(F_struc(end-K.s(end)^2+1:end,:),2);
X = reshape(X,K.s(end),K.s(end));
[v,dummy,r,dummy2]=dmperm(X);
blks = diff(r);

lint = F_struc(1:end-K.s(end)^2,:);
logt = F_struc(end-K.s(end)^2+1:end,:);

newlogt = [];
for i = 1:size(logt,2)
    temp = reshape(logt(:,i),K.s(end),K.s(end));
    temp = temp(v,v);
    newlogt = [newlogt temp(:)];
end
logt = newlogt;

pattern = [];
for i = 1:length(blks)
    pattern = blkdiag(pattern,ones(blks(i)));
end

F_struc = [lint;logt(find(pattern),:)];
K.s(end) = [];
K.s = [K.s blks];
K.m = blks;



function S = createSchurFun(options,K,interfacedata,i);
S.extra.par = options.sdpt3;    
S.data = K.schur_data{i};
[init,loc] = ismember(K.schur_variables{i},interfacedata.used_variables);
S.index = loc;
S.fun =  K.schur_funs{i};
S.nvars = length(interfacedata.used_variables);
%options.sdpt3.schurfun_par{top,1} = S;
%  V = {S.extra,S.data{:}};
%  feval(S.fun,[],[],V{:});
