function [pnew,llf,marq]=mmlemarq(p,pid,p2snam,gg,marq,llf)
% USED BY MMLE.M TO GET NEAR MINIMUM (=>QUADRATIC AREA ) OF COST FUNCTION

 % -  USES FUNCTIONS mmlelike, AND USER CREATED FUNCTION p2ss.
 % -  COMPUTES PARAMETER VECTOR "pnew" TO IMPROVE llf FOR TOUGH PROBLEMS.
 % -  USES MARQUARD PARAMETER marq TO FIND BEST GAIN/DIRECTION COMPROMISE OF
 %       GRADIENT AND NEWTON UPDATE TO OBTAIN THE BEST llf IMPROVEMENT
 %            FROM EACH EXPENSIVE GRADIENT/HESSIAN COMPUTATION.
 % -  marq >>1 GIVES SLOW GRADIENT ALGO.
 % -  marq <<1 APPROACHES NEWTON UPDATE.
 % -  marq =0 DEFAULTS TO marq =1.
 % -  marq IS AUTOMATICALLY REDUCED AS FAST AS PROBLEM PERMITS
 %         TO SPEED USE OF CONSTRAINED NEWTON ALGO BY mmle.m
 % -  pnew IS NEW PARAM, llf IS BEST llf, marq IS LAST marq.
 % -  mmlestep, mmlelike DESCRIBE THE OTHER VARIABLES.
 %---------------------------------------------------------------------------


global hes
global wersum
global grad
global rr


eyenpid = eye(length(pid));
%----------------------------------------SCALE UNITS FOR UNIT DIAGONAL
scale = diag(exp(-.5*log(diag(hes))));
shes = scale*hes*scale;sgrad = scale*grad;
%
pnew_t=p;pnew=p;if marq == 0,marq = 1;end %   DEFAULT OPTION
trend     = 0; %  MEANINGS =>>>   0:FIRST LOOP, -1:WAS WORSE, +1:WAS BETTER

%------------------------------------------------DISPLAY MAX GRADIENT ELEMENT
absgr=abs(grad);mgr=max(absgr);igr=find(absgr==mgr);
ans4=sprintf('%f',mgr);ans5=sprintf('%f',pid(igr));
ans1=[' --- MMLEMARQ ---   max(abs(grad)) = ',ans4(1:8), ...
          ' -- p( ',ans5(1:2),')'];disp(ans1)
%--------------------------------------------------------------START LOOP
for nstep = 1:5,
  ans =-scale*real((shes+marq*eyenpid)\sgrad ); %  PARAMETER STEP
  pnew_t(pid)=p(pid) + ans'; %                     TRIAL PARAMETER VECTOR
  [llf_t,wersum_t,rr_t] = mmlelike( pnew_t, p2snam, gg );%    GET ITS LLF
    if llf_t==NaN;llf_t=8888888;end;
  ans1=sprintf('%f',marq);ans2=sprintf('%f',llf);
  ans3=sprintf('%f',llf_t);ans4=sprintf('%f',wersum_t);
  ans4=[ ' marq = ', ans1(1:7), '   best llf = ',ans2(1:7),...
   '   trial llf = ', ans3(1:7),'   wersum = ',ans4(1:7)];disp(ans4)

%-----------------------------------------------------MARQUARDT DECISIONS
  if llf_t > llf, %           LLF IS WORSE
      if trend == 1,return,end %   WAS BETTER, NOW WORSE => RETURN
         if trend == -1,
         if abs(llf_t-llf)<.5,return% BACK WITHIN .5 OF BEST LLF => RETN
         end,end
      marq=marq*10; %         INCREASE MARQ
      trend=-1; %             REMEMBER THIS STEP WAS WORSE
   else
      llf=llf_t;rr=rr_t;%     UPDATE BEST LLF,RR
      wersum=wersum_t; %      WERSUM
      pnew=pnew_t; %          SAVE BEST PARAMETERS FOUND
         if trend == -1, return,end %   MARQ NOW HIGH ENOUGH TO RETURN
      mold=marq;marq = marq/sqrt(10);
      trend=1; %              REMEMBER THIS WAS BETTER
   end
end %                         END OF 'FOR' LOOP
return
%------------------------------------------------------------- end mmlemarq

