/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: matec.c,v $
 * Revision 1.5  1993/01/18  18:12:15  lotos
 * distribution issues
 *
 * Revision 1.4  1992/10/14  17:43:36  lotos
 * forget about ophuscation
 *
 * Revision 1.3  1992/01/14  15:25:16  lotos
 * distribution issues
 *
 * Revision 1.2  92/01/13  19:24:43  lotos
 * adaptec to ophuscate
 * 
 * Revision 1.1  91/02/06  20:15:18  lotos
 * Initial revision
 * 
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: matec.c,v 1.5 1993/01/18 18:12:15 lotos Exp $";
#endif

/***********************************************************************

     "matec.o": modulo de gestion de matrices esfericas de ECxARG.

***********************************************************************/

#include <stdio.h>
#include "idle.h"
#include "matec.h"


/*
     Cualquier operacion  sobre una matriz, que  involucre a un elemento
(ecuacion o argumento)  o posicion de  dicha matriz,  se realizara sobre
el(la) siguiente al origen (en la direccion adecuada).
     La supresion o  extraccion  de  un elemento  (ecuacion o argumento)
de una matriz, no conlleva  ningun cambio de  origen;  a lo sumo, que la
matriz se convierta  en nula. Sin embargo, cuando se produce una agrega-
cion,  el nuevo  elemento pasa a ser el origen.  Si la agregacion  viene
motivada  por una operacion de  copia de elementos  entre  matrices,  el
elemento de la matriz  origen del que se hizo  la copia,  tambien pasa a
ser origen.
*/


void InicMatEcxArg(MatObj, EcInic)
/* Inicia la construccion de una matriz de ecs. por args. */
EstEcxArg *MatObj;	/* Matriz objeto. */
EstManEc *EcInic;	/* Ecuacion inicial. */
{ EstArgEc *ArgInic;	/* Argumento inicial. */

  aborta_si(MatEcxArgIncorr(MatObj) ||
	    MatObj->EcOrig != NULL)
  if (EcInic == NULL)
    EcInic= AsigMem(EstManEc, 1);
  EcInic->SigEc= EcInic;
  MatObj->EcOrig= EcInic;
  ArgInic= AsigMem(EstArgEc, 1);
  ArgInic->SigArg= ArgInic;
  ArgInic->SigEc= ArgInic;
  MatObj->ArgEcOrig= ArgInic;
}

void AgrArgMat(MatObj)
/* Agrega un argumento a una matriz de ecs. por args. */
EstEcxArg *MatObj;	/* Matriz objeto. */
{ EstArgEc *ArgPrimEc;	/* Argumento en la primera ecuacion. */
  EstArgEc *ArgEcAct;	/* Argumento en la ecuacion actual. */
  EstArgEc *ArgAgrAnt;	/* Argumento a agregar anterior. */
  EstArgEc *ArgAgrAct;	/* Argumento a agregar actual. */

  aborta_si(MatEcxArgIncorr(MatObj) ||
	    MatObj->EcOrig == NULL)
  ArgEcAct= ArgPrimEc= MatObj->ArgEcOrig;
  ArgAgrAct= AsigMem(EstArgEc, 1);
  for (;;)
  { ArgAgrAct->SigArg= ArgEcAct->SigArg;
    ArgEcAct->SigArg= ArgAgrAct;
    ArgEcAct= ArgEcAct->SigEc;
    if (ArgEcAct == ArgPrimEc)
      break;
    ArgAgrAnt= ArgAgrAct;
    ArgAgrAct= AsigMem(EstArgEc, 1);
    ArgAgrAnt->SigEc= ArgAgrAct;
  }
  ArgAgrAct->SigEc= MatObj->ArgEcOrig= ArgPrimEc->SigArg;
}

void SuprArgMat(MatObj)
/* Suprime un argumento de una matriz de ecs. por args. */
EstEcxArg *MatObj;	/* Matriz objeto. */
{ EstArgEc *ArgPrimEc;	/* Argumento en la primera ecuacion. */
  EstArgEc *ArgEcAct;	/* Argumento en la ecuacion actual. */
  EstArgEc *ArgSupr;	/* Argumento a suprimir. */

  aborta_si(MatEcxArgIncorr(MatObj) ||
	    MatObj->EcOrig == NULL)
  ArgEcAct= ArgPrimEc= MatObj->ArgEcOrig;
  if (ArgPrimEc->SigArg == ArgPrimEc)
  { /* Ultimo argumento de la matriz. */
    EstManEc *PrimEc;	/* Primera ecuacion. */
    EstManEc *EcAct;	/* Ecuacion actual. */
    EstManEc *EcSupr;	/* Ecuacion a suprimir. */

    /* Supresion de las ecuaciones. */
    EcAct= PrimEc= MatObj->EcOrig;
    do
    { EcSupr= EcAct;
      EcAct= EcAct->SigEc;
      LibMem(EcSupr);
    } while (EcAct != PrimEc);
    MatObj->EcOrig= NULL;
    /* Supresion del argumento. */
    do
    { ArgSupr= ArgEcAct;
      ArgEcAct= ArgEcAct->SigEc;
      LibMem(ArgSupr);
    } while (ArgEcAct != ArgPrimEc);
    MatObj->ArgEcOrig= NULL;
  }
  else
    /* Hay mas de un argumento en la matriz. */
    /* Supresion del argumento. */
    do
    { ArgSupr= ArgEcAct->SigArg;
      ArgEcAct->SigArg= ArgSupr->SigArg;
      LibMem(ArgSupr);
      ArgEcAct= ArgEcAct->SigEc;
    } while (ArgEcAct != ArgPrimEc);
}

void AgrEcMat(MatObj, EcAgr)
/* Agrega una ecuacion a una matriz de ecs. por args. */
EstEcxArg *MatObj;	/* Matriz objeto. */
EstManEc *EcAgr;	/* Ecuacion a agregar. */
{ EstManEc *PrimEc;	/* Primera ecuacion. */
  EstArgEc *PrimArgEc;	/* Primer argumento de una ecuacion. */
  EstArgEc *ArgActEc;	/* Argumento actual de una ecuacion. */
  EstArgEc *ArgAgrAnt;	/* Argumento a agregar anterior. */
  EstArgEc *ArgAgrAct;	/* Argumento a agregar actual. */

  aborta_si(MatEcxArgIncorr(MatObj) ||
	    MatObj->EcOrig == NULL)
  /* Agregacion de la ecuacion. */
  if (EcAgr == NULL)
    EcAgr= AsigMem(EstManEc, 1);
  PrimEc= MatObj->EcOrig;
  EcAgr->SigEc= PrimEc->SigEc;
  MatObj->EcOrig= PrimEc->SigEc= EcAgr;
  /* Agregacion de los argumentos. */
  ArgActEc= PrimArgEc= MatObj->ArgEcOrig;
  ArgAgrAct= AsigMem(EstArgEc, 1);
  for (;;)
  { ArgAgrAct->SigEc= ArgActEc->SigEc;
    ArgActEc->SigEc= ArgAgrAct;
    ArgActEc= ArgActEc->SigArg;
    if (ArgActEc == PrimArgEc)
      break;
    ArgAgrAnt= ArgAgrAct;
    ArgAgrAct= AsigMem(EstArgEc, 1);
    ArgAgrAnt->SigArg= ArgAgrAct;
  }
  ArgAgrAct->SigArg= MatObj->ArgEcOrig= PrimArgEc->SigEc;
}

void SuprEcMat(MatObj)
/* Suprime una ecuacion de una matriz de ecs. por args. */
EstEcxArg *MatObj;	/* Matriz objeto. */
{ EstManEc *PrimEc;	/* Primera ecuacion. */
  EstManEc *EcSupr;	/* Ecuacion a suprimir. */
  EstArgEc *PrimArgEc;	/* Primer argumento de una ecuacion. */
  EstArgEc *ArgActEc;	/* Argumento actual de una ecuacion. */
  EstArgEc *ArgSupr;	/* Argumento a suprimir. */

  aborta_si(MatEcxArgIncorr(MatObj) ||
	    MatObj->EcOrig == NULL)
  ArgActEc= PrimArgEc= MatObj->ArgEcOrig;
  if (PrimArgEc->SigEc == PrimArgEc)
  { /* Solo hay una ecuacion en la matriz. */
    /* Supresion de la ecuacion. */
    EcSupr= MatObj->EcOrig;
    LibMem(EcSupr);
    MatObj->EcOrig= NULL;
    /* Supresion de los argumentos. */
    do
    { ArgSupr= ArgActEc;
      ArgActEc= ArgActEc->SigArg;
      LibMem(ArgSupr);
    } while (ArgActEc != PrimArgEc);
    MatObj->ArgEcOrig= NULL;
  }
  else
  { /* Hay mas de una ecuacion en la matriz. */
    /* Supresion de la ecuacion. */
    PrimEc= MatObj->EcOrig;
    EcSupr= PrimEc->SigEc;
    PrimEc->SigEc= EcSupr->SigEc;
    LibMem(EcSupr);
    /* Supresion de los argumentos. */
    do
    { ArgSupr= ArgActEc->SigEc;
      ArgActEc->SigEc= ArgSupr->SigEc;
      LibMem(ArgSupr);
      ArgActEc= ArgActEc->SigArg;
    } while (ArgActEc != PrimArgEc);
  }
}

void SuprMatEcxArg(MatObj)
/* Suprime una matriz de ecs. por args. */
EstEcxArg *MatObj;	/* Matriz objeto. */
{
  aborta_si(MatEcxArgIncorr(MatObj) ||
	    MatObj->EcOrig == NULL)
  do
    SuprEcMat(MatObj);
  while (MatObj->EcOrig != NULL);
}

void MueveEcMat(MatOrig, MatDest)
/* Mueve una ecuacion de una a otra matriz de ecs. por args. */
EstEcxArg *MatOrig;	/* Matriz origen. */
EstEcxArg *MatDest;	/* Matriz destino. */
{ EstManEc *PrimEc;	/* Primera ecuacion */
  EstManEc *EcMov;	/* Ecuacion a mover. */
  EstArgEc *PrimArgEc;	/* Primer argumento de una ecuacion. */
  EstArgEc *ArgActEc;	/* Argumento actual de una ecuacion. */
  EstArgEc *PrimArgMov;	/* Primer argumento a mover. */
  EstArgEc *ArgActMov;	/* Argumento actual a mover. */

  aborta_si(MatEcxArgIncorr(MatOrig) ||
	    MatEcxArgIncorr(MatDest) ||
	    MatOrig->EcOrig == NULL)
  /* Extraccion de la ecuacion a mover. */
  ArgActEc= PrimArgEc= MatOrig->ArgEcOrig;
  if (PrimArgEc->SigEc == PrimArgEc)
  { /* Solo hay una ecuacion en la matriz origen. */
    EcMov= MatOrig->EcOrig;
    MatOrig->EcOrig= NULL;
    PrimArgMov= PrimArgEc;
    MatOrig->ArgEcOrig= NULL;
  }
  else
  { /* Hay mas de una ecuacion en la matriz origen. */
    PrimEc= MatOrig->EcOrig;
    EcMov= PrimEc->SigEc;
    PrimEc->SigEc= EcMov->SigEc;
    PrimArgMov= PrimArgEc->SigEc;
    do
    { ArgActEc->SigEc= ArgActEc->SigEc->SigEc;
      ArgActEc= ArgActEc->SigArg;
    } while (ArgActEc != PrimArgEc);
  }
  /* Agregacion de la ecuacion a mover. */
  if (MatDest->EcOrig == NULL)
  { /* La matriz destino es nula. */
    MatDest->EcOrig= EcMov;
    MatDest->ArgEcOrig= PrimArgMov;
    if (PrimArgMov->SigEc != PrimArgMov)
    { /* La matriz origen tenia mas de una ecuacion. */
      EcMov->SigEc= EcMov;
      ArgActMov= PrimArgMov;
      do
      { ArgActMov->SigEc= ArgActMov;
	ArgActMov= ArgActMov->SigArg;
      } while (ArgActMov != PrimArgMov);
    }
  }
  else
  { /* La matriz destino no es nula. */
    PrimEc= MatDest->EcOrig;
    EcMov->SigEc= PrimEc->SigEc;
    MatDest->EcOrig= PrimEc->SigEc= EcMov;
    ArgActEc= PrimArgEc= MatDest->ArgEcOrig;
    ArgActMov= PrimArgMov;
    do
    { ArgActMov->SigEc= ArgActEc->SigEc;
      ArgActEc->SigEc= ArgActMov;
      ArgActEc= ArgActEc->SigArg;
      ArgActMov= ArgActMov->SigArg;
    } while (ArgActMov != PrimArgMov);
    aborta_si(ArgActEc != PrimArgEc ||
	      PrimArgEc->SigEc != PrimArgMov)
    MatDest->ArgEcOrig= PrimArgMov;
  }
}

void CopiaEcMat(MatOrig, MatDest)
/* Copia una ecuacion de una a otra matriz de ecs. por args. */
EstEcxArg *MatOrig;	/* Matriz origen. */
EstEcxArg *MatDest;	/* Matriz destino. */
{ EstManEc *EcCop;	/* Ecuacion a copiar. */
  EstManEc *PrimEc;	/* Primera ecuacion. */
  EstManEc *EcAgr;	/* Ecuacion a agregar. */
  EstArgEc *PrimArgCop;	/* Primer argumento a copiar. */
  EstArgEc *ArgActCop;	/* Argumento actual a copiar. */
  EstArgEc *PrimArgEc;	/* Primer argumento de una ecuacion. */
  EstArgEc *ArgActEc;	/* Argumento actual de una ecuacion. */
  EstArgEc *PrimArgAgr;	/* Primer argumento a agregar. */
  EstArgEc *ArgAgrAnt;	/* Argumento a agregar anterior. */
  EstArgEc *ArgAgrAct;	/* Argumento a agregar actual. */

  aborta_si(MatEcxArgIncorr(MatOrig) ||
	    MatEcxArgIncorr(MatDest) ||
	    MatOrig->EcOrig == NULL)
  /* Seleccion de la ecuacion a copiar. */
  EcCop= MatOrig->EcOrig->SigEc;
  MatOrig->EcOrig= EcCop;
  PrimArgCop= MatOrig->ArgEcOrig->SigEc;
  MatOrig->ArgEcOrig= PrimArgCop;
  /* Agregacion de la copia de la ecuacion. */
  if (MatDest->EcOrig == NULL)
  { /* La matriz destino es nula. */
    PrimEc= AsigMem(EstManEc, 1);
    PrimEc->SigEc= PrimEc;
    PrimEc->Premisas= EcCop->Premisas;
    PrimEc->EcSimple= EcCop->EcSimple;
    MatDest->EcOrig= PrimEc;
    ArgActCop= PrimArgCop;
    ArgAgrAct= PrimArgAgr= AsigMem(EstArgEc, 1);
    for (;;)
    { ArgAgrAct->SigEc= ArgAgrAct;
      ArgAgrAct->NodoArg= ArgActCop->NodoArg;
      ArgActCop= ArgActCop->SigArg;
      if (ArgActCop == PrimArgCop)
	break;
      ArgAgrAnt= ArgAgrAct;
      ArgAgrAct= AsigMem(EstArgEc, 1);
      ArgAgrAnt->SigArg= ArgAgrAct;
    }
    ArgAgrAct->SigArg= MatDest->ArgEcOrig= PrimArgAgr;
  }
  else
  { /* La matriz destino no es nula. */
    PrimEc= MatDest->EcOrig;
    EcAgr= AsigMem(EstManEc, 1);
    EcAgr->SigEc= PrimEc->SigEc;
    PrimEc->SigEc= EcAgr;
    EcAgr->Premisas= EcCop->Premisas;
    EcAgr->EcSimple= EcCop->EcSimple;
    MatDest->EcOrig= EcAgr;
    ArgActEc= PrimArgEc= MatDest->ArgEcOrig;
    ArgActCop= PrimArgCop;
    ArgAgrAct= PrimArgAgr= AsigMem(EstArgEc, 1);
    for (;;)
    { ArgAgrAct->SigEc= ArgActEc->SigEc;
      ArgActEc->SigEc= ArgAgrAct;
      ArgAgrAct->NodoArg= ArgActCop->NodoArg;
      ArgActEc= ArgActEc->SigArg;
      ArgActCop= ArgActCop->SigArg;
      if (ArgActCop == PrimArgCop)
	break;
      ArgAgrAnt= ArgAgrAct;
      ArgAgrAct= AsigMem(EstArgEc, 1);
      ArgAgrAnt->SigArg= ArgAgrAct;
    }
    aborta_si(ArgActEc != PrimArgEc ||
	      PrimArgEc->SigEc != PrimArgAgr)
    ArgAgrAct->SigArg= MatDest->ArgEcOrig= PrimArgAgr;
  }
}
