/* -*- mode: maxima -*- */
eval_when(batch,ttyoff:true)$
/*ASB;LRATS 3
5:05pm  Tuesday, 14 July 1981
7:53pm  Saturday, 29 May 1982
  Added a DIAGEVAL_VERSION for this file.
1:43pm  Saturday, 12 June 1982
  Changed loadflags to getversions, DEFINE_VARIABLE:'MODE.
*/

eval_when(translate,
	  define_variable:'mode)$

put('lrats,3,'diageval_version)$

define_variable(messlrats2,"Invalid argument to FULLRATSUBST:",any)$

define_variable(fullratsubstflag,false,boolean)$

lratsubst(listofeqns,expr):=block(
  [partswitch:true,inflag:true,piece],
  if not listp(listofeqns)
  then if inpart(listofeqns,0)="="
       then listofeqns:[listofeqns]
       else if fullratsubstflag=true
            then error(messlrats2,[listofeqns,expr])
            else error("Invalid argument to lratsubst:",[listofeqns,expr]),
  if listp(inpart(listofeqns,1)) then if length(listofeqns)>1 then error("lratsubst: improper argument:",listofeqns) else listofeqns:inpart(listofeqns,1),
  for idum in listofeqns do
      if inpart(idum,0)#"="
      then if fullratsubstflag=true
           then error(messlrats2,[listofeqns,expr])
	   else error("Invalid argument to lratsubst:",[listofeqns,expr]),
  lratsubst1(listofeqns,expr))$

define_variable(lrats_max_iter,100000,integer)$
qput(lrats_max_iter,lambda([v], if v<=0 then error("lrats_max_iter must be set to a positive integer.")),value_check);

lratsubst1(listofeqns,expr):=block([dum,lrats_iter:0],
  for eqn in listofeqns do [dum,expr]:[expr,ratsubst(inpart(eqn,2),inpart(eqn,1),expr)],
  expr)$

fullratsubst0(eqn,expr):= fullratsubst1(second(eqn),first(eqn),expr)$

fullratsubst1(substexpr,forexpr,expr):=fullratsubst2([forexpr=substexpr],expr)$

fullratsubst2(listofeqns,expr):=block(
  [dum,lrats_iter:0],
  while lrats_iter<lrats_max_iter and dum#expr do (
    [dum,expr]:[expr,lratsubst1(listofeqns,expr)],
    lrats_iter:1+lrats_iter),
  if lrats_iter>=lrats_max_iter then warning("fullratsubst2(listofeqns,expr): reached maximum iterations of",lrats_max_iter,". Increase `lrats_max_iter' to increase this limit."),
  expr)$

fullratsubst([arglist]):=block(
  [larglistdum:length(arglist),farglist,partswitch:true,inflag:true,piece],
  if larglistdum=2
  then (farglist:first(arglist),
    if listp(farglist) then fullratsubst2(farglist,second(arglist))
    else if inpart(farglist,0)="=" then fullratsubst0(farglist,last(arglist))
    else error(messlrats2,arglist))
  else if larglistdum=3
  then apply('fullratsubst1,arglist)
  else error(messlrats2,arglist))$

eval_when(batch,ttyoff:false)$
