function [stat,post] = blkalgexp(path,prop,bstr,bint,bflt,parent,name,catalog,ws,node,sbSample)
%BLKALGEXP Defines a set of algebraic expressions.
%
%  See also BLKLOGEXP

% Initial coding by A S Bozin, 5-30-97
% Copyright 1997-2000 The MathWorks, Inc.
% $Revision: 1.9 $ $Date: 2000/06/14 16:08:33 $

   stat = 0;					   % Error flag
   nInputs = bint(5);
   nOutputs = bint(6);
   %
   % Add mux and demux blocks if necessary
   %
   [post,rect] = blkio('port',nInputs,nOutputs,prop,path);
   %
   % Get the pseudo code and the parameter vector
   %
   indInt = bint(15)+1;
   indStr = bint(17)+1;
   npar = 2;
   symInd = zeros(1,npar);
   if (bitand(bint(indInt),16))
      indVar = indInt+2;
      vRange = 1:bint(indVar);
      symInd(bint(indVar+vRange)) = 1;
   end
   str = cell(npar,1);
   for (k = find(symInd))
      ind = mfindstr(bstr,indStr,'|');
      str{k} = bstr(indStr:ind-1);
      indStr = ind+1;
   end
   %
   % Get the block parameter variables
   %
   [symInd,str] = mgetscope(symInd,str,catalog,ws,node);
   indFlt = bint(19);
   bFile = bint(18)+1;
   bFile = bFile+bint(bFile);			   % Skip icon data
   nData = bint(bFile);
   nPara = bint(bFile+1);
   stkSize = bint(bFile+3);
   nCode = bint(bFile+4);
   pLen = [nData;nPara];
   ub = cumsum(pLen);
   lb = [0;ub(1:end-1)]+1;
   for (k = find(~symInd))
      if (k == 1)
	 bCode = bFile+4;
	 cRange = 1:nCode;
	 code = bint(bCode+cRange);
	 dRange = lb(k):ub(k);
	 data = bflt(indFlt+dRange);
	 str{1} = pdecode(code,data,stkSize);
      else
	 pRange = lb(k):ub(k);
	 str{k} = mat2char(bflt(indFlt+pRange));
      end
   end
   %
   %
   %
   copt = 0;					   % Optimization level
   if (prop.optimize)
      src = evalin('base',str{1});
      par = evalin('base',str{2});
      [flag,code,data,info] = algexp2pc(src);
      if (isempty(flag))
	 [eqn,op1,op2] = algexpeqn(info,code);
	 if (~isempty(eqn))
	    if ((all(eqn == 1) & all(op1 == 1)) | ...
		((all(eqn == 2) | all(eqn == 3) | all(eqn == 4) | all(eqn == 5) | all(eqn == 6)) & ...
		 all(op1 == 1) & all(op2 == 1)))
	       copt = 1;
	    elseif (((all(eqn == 4) | all(eqn == 5)) & all(op1 == 2) & all(op2 == 1)) | ...
		    (all(eqn == 1) & all(op1 == 2)))
	       copt = 2;
	    elseif ((all(eqn == 4) | all(eqn == 5)) & all(op1 == 2) & all(op2 == 2))
	       copt = 3;
	    elseif (all(eqn == 5) & all(op1 == 1) & all(op2 == 2))
	       copt = 4;
	    elseif (all((eqn == 2) | (eqn == 3)) & all(op1 == 2) & all(op2 == 1))
	       copt = 5;
	    elseif (all((eqn == 2) | (eqn == 3)) & all(op1 == 2) & all(op2 == 2))
	       copt = 6;
	    elseif (all(eqn == 6) & all(op1 == 1) & all(op2 == 2))
	       copt = 7;
	    else
	       copt = 0;
	    end
	 end
      else
	 error(flag);
      end
   end
   %
   % Algebraic expression block
   %
   switch (copt)
   case 0
      bh = add_block('libsb2sl/ALG/AlgExpression/General',path,'TS',mat2char(sbSample));
   case 1
      bh = add_block('libsb2sl/ALG/AlgExpression/Constant',path);
   case 2
      bh = add_block('libsb2sl/ALG/AlgExpression/Scale',path);
   case 3
      bh = add_block('libsb2sl/ALG/AlgExpression/Product',path);
   case 4
      bh = add_block('libsb2sl/ALG/AlgExpression/Reciprocal',path);
   case 5
      bh = add_block('libsb2sl/ALG/AlgExpression/Offset',path);
   case 6
      bh = add_block('libsb2sl/ALG/AlgExpression/Summation',path);
   case 7
      bh = add_block('libsb2sl/ALG/AlgExpression/PowerCU',path);
   otherwise
   end
   %
   % Common block properties
   %
   set_param(bh,'ForegroundColor',prop.fgColor,...
		'BackgroundColor',prop.bgColor,...
		'Orientation',prop.orientation,...
		'DropShadow',prop.border,...
		'Position',rect,...
		'SRC',str{1},...
		'P0',str{2});
   %
   % Connect the current algebraic expression block with the mux and demux blocks
   %
   blkio('line',nInputs,nOutputs,post,parent,name);
   return					   % Last card of BLKALGEXP

function src = pdecode(code,data,stksize)
%PDECODE
%
%

   nCode = size(code,2);
   pc = 1;
   stack = cell(stksize,1);			   % Stack
   stype = zeros(stksize,1);
   tos = 0;					   % Top of the stack
   quote = char(39);				   % String delimiter
   src = quote;
   opsym = cell(19,1);
   opsym(13:17) = {'-';' + ';' - ';...
		   ' * ';' / '};
   while (pc < nCode)
      opCode = code(pc);
      pc = pc+1;
      switch (opCode)
      case 1					   % Push T
	 tos = tos+1;
	 stack{tos} = 'T';
	 stype(tos) = 0;
      case 2					   % Push U
	 tos = tos+1;
	 stack{tos} = sprintf('U%d',code(pc));
	 stype(tos) = 0;
	 pc = pc+1;
      case 4					   % Push NUM
	 tos = tos+1;
	 stack{tos} = sprintf('%g',data(code(pc)));
	 stype(tos) = 0;
	 pc = pc+1;
      case 5					   % Push P
	 tos = tos+1;
	 stack{tos} = sprintf('P%d',code(pc));
	 stype(tos) = 0;
	 pc = pc+1;
      case 7					   % Push Y
	 tos = tos+1;
	 stack{tos} = sprintf('Y%d',code(pc));
	 stype(tos) = 0;
	 pc = pc+1;
      case 9					   % Pop P
	 src = sprintf('%sP%d = %s;',src,code(pc),stack{tos});
	 pc = pc+1;
	 tos = tos-1;
      case 11				   	   % Pop Y
	 src = sprintf('%sY%d = %s;',src,code(pc),stack{tos});
	 pc = pc+1;
	 tos = tos-1;
      case 13				   	   % Unary minus
	 if (stype(tos) < 3)
	    fmt = '%s%s';
	 else
	    fmt = '%s(%s)';
	 end
	 stack{tos} = sprintf(fmt,opsym{opCode},stack{tos});
	 stype(tos) = 3;
      case {14,15}			   	   % Plus, minus
	 tos = tos-1;
	 if (stype(tos+1) < 3)
	    fmt = '%s%s%s';
	 else
	    fmt = '%s%s(%s)';
	 end
	 stack{tos} = sprintf(fmt,stack{tos},opsym{opCode},stack{tos+1});
	 stype(tos) = 3;
      case {16,17}			   	   % Multiply, divide
	 tos = tos-1;
	 if (stype(tos) <= 2)
	    if (stype(tos+1) < 2)
	       fmt = '%s%s%s';
	    else
	       fmt = '%s%s(%s)';
	    end
	 else
	    if (stype(tos+1) < 2)
	       fmt = '(%s)%s%s';
	    else
	       fmt = '(%s)%s(%s)';
	    end
	 end
	 stack{tos} = sprintf(fmt,stack{tos},opsym{opCode},stack{tos+1});
	 stype(tos) = 2;
      case {18,19}				   % Power
	 tos = tos-1;
	 if (stype(tos) <= 1)
	    if (stype(tos+1) <= 1)
	       fmt = '%s ** %s';
	    else
	       fmt = '%s ** (%s)';
	    end
	 else
	    if (stype(tos+1) <= 1)
	       fmt = '(%s) ** %s';
	    else
	       fmt = '(%s) ** (%s)';
	    end
	 end
	 stack{tos} = sprintf(fmt,stack{tos},stack{tos+1});
	 stype(tos) = 1;
      otherwise
      end
   end
   src = cat(2,src,quote);
   return					   % Last card of PDECODE
