/* -*- MACSYMA -*- */
EVAL_WHEN(BATCH,TTYOFF:TRUE)$
/*ASB;FACEX1 1
4:19pm  Monday, 7 February 1983
  Split off from FACEXP 15
*/

EVAL_WHEN([TRANSLATE,BATCH,LOADFILE],
	  IF GET('FACEXP,'VERSION)=FALSE
	  THEN (LOAD('[FACEXP,FASL]),
		LOAD('[GNDECL,FASL])))$

EVAL_WHEN(TRANSLATE,
	  TRANSCOMPILE:TRUE,
	  DEFINE_VARIABLE:'MODE,
	  MODEDECLARE(FUNCTION(NULLLISTP,FREEOFL),BOOLEAN))$

PUT('FACEX1,1,'VERSION)$

COLLECTTEN(EXP):=COLLECTTERMSL(EXP,LISTOFTENS(EXP))$

COLLECTTERMS(EXP,[VARLIST]):=COLLECTTERMSL(EXP,VARLIST)$

COLLECTTERMSL(EXP,VARLIST):=BLOCK(
  [PARTSWITCH:TRUE,INFLAG:TRUE,PIECE],
  APPLY('COLLECTTERMS0,CONS(EXP,ARGSPLIT(EXP,VARLIST))))$

COLLECTTERMS0(EXP,THISLEVELDUM,NEXTLEVELDUM):=BLOCK(
  [IFORP:TRUE,SPLITDUM1,SPLITDUM2,SPLITDUM3,ANSLIST:[],FDUM,
   PREVDUM,LSPLIT3,ANSDUM,LASTDUMSAVE,PREVLASTDUM,
   RTHISLEVELDUM,FTHISLEVELDUM],
  MODEDECLARE(LSPLIT3,FIXNUM),
  DECLARE([FDUM,SPLITDUM3,ANSDUM],SPECIAL),
  IF EXP=0 THEN RETURN(0),
  IF NULLLISTP(THISLEVELDUM) OR FREEOFL(THISLEVELDUM,EXP)
  THEN IF NULLLISTP(NEXTLEVELDUM)
       THEN RETURN(EXP)
       ELSE (SPLITDUM1:ORPARTITIONL(EXP,"+",NEXTLEVELDUM),
	     RETURN(COLLECTTERMSL(FIRST(SPLITDUM1),NEXTLEVELDUM)
		    +IFLOPMAP("+",
			      LAMBDA([TERMDUM],
				     COLLECTTERMSL(TERMDUM,NEXTLEVELDUM)),
			      LAST(SPLITDUM1)))),
  RTHISLEVELDUM:REST(THISLEVELDUM),
  IF FREEOF(FTHISLEVELDUM:FIRST(THISLEVELDUM),EXP)
  THEN RETURN(COLLECTTERMS0(EXP,RTHISLEVELDUM,NEXTLEVELDUM)),
  SPLITDUM1:ORPARTITIONL(EXP,"+",THISLEVELDUM),
  SPLITDUM2:ORPARTITIONL(LAST(SPLITDUM1),"+",[FTHISLEVELDUM]),
  ANSDUM:COLLECTTERMSL(FIRST(SPLITDUM1),NEXTLEVELDUM)
	 +COLLECTTERMS0(FIRST(SPLITDUM2),RTHISLEVELDUM,NEXTLEVELDUM),
  IF INPART(SPLITDUM3:LAST(SPLITDUM2),0)#"+"
  THEN RETURN(ANSDUM+COLLECTTERMSL(SPLITDUM3,NEXTLEVELDUM)),
  SPLITDUM3:SORT(MAPLIST(LAMBDA([TERM],ORPARTITIONL(TERM,"*",[FTHISLEVELDUM])),
		 SPLITDUM3),
		 'ORDERLASTP),
  LSPLIT3:LENGTH(SPLITDUM3)-1,
  PREVLASTDUM:INPART(SPLITDUM3,1,2),
  PREVDUM:INPART(SPLITDUM3,1,1),
  SPLITDUM3:REST(SPLITDUM3),
  FOR IDUM THRU LSPLIT3 DO
       (IF (LASTDUMSAVE:INPART(SPLITDUM3,IDUM,2))=PREVLASTDUM
	THEN PREVDUM:PREVDUM+INPART(SPLITDUM3,IDUM,1)
	ELSE (ANSLIST:ENDCONS([PREVDUM,PREVLASTDUM],ANSLIST),
	      PREVDUM:INPART(SPLITDUM3,IDUM,1),
	      PREVLASTDUM:LASTDUMSAVE),
	IF IDUM=LSPLIT3
	THEN ANSLIST:ENDCONS([PREVDUM,PREVLASTDUM],ANSLIST)),
  LISTTOSUM(MAPLIST(LAMBDA([DUM],
			   IF FREEOFL(RTHISLEVELDUM,FDUM:FIRST(DUM))
			   THEN COLLECTTERMSL(FDUM,NEXTLEVELDUM)
				    *LAST(DUM)
			   ELSE MULTTHRUSPLIT(LAST(DUM),
					      COLLECTTERMS0(FDUM,RTHISLEVELDUM,
							    NEXTLEVELDUM),
					      RTHISLEVELDUM)),
		    ANSLIST))+ANSDUM)$

ORDERLASTP(EXP1,EXP2):=ORDERLESSP(LAST(EXP1),LAST(EXP2))$


MULTTHRUSPLIT(FACTORDUM,SUMDUM,RTHISLEVELDUM):=BLOCK(
  [SPLITDUM1:ORPARTITIONL(SUMDUM,"+",RTHISLEVELDUM)],
  MULTTHRU(FACTORDUM,LAST(SPLITDUM1))+FACTORDUM*FIRST(SPLITDUM1))$

EVAL_WHEN(BATCH,TTYOFF:FALSE)$
