/* glpeta.c */

/*----------------------------------------------------------------------
-- Copyright (C) 2000, 2001, 2002 Andrew Makhorin <mao@mai2.rcnet.ru>,
--               Department for Applied Informatics, Moscow Aviation
--               Institute, Moscow, Russia. All rights reserved.
--
-- This file is a part of GLPK (GNU Linear Programming Kit).
--
-- GLPK is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
--
-- GLPK is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-- License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with GLPK; see the file COPYING. If not, write to the Free
-- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
----------------------------------------------------------------------*/

#include <stddef.h>
#include "glpeta.h"

/*----------------------------------------------------------------------
-- create_eta - create eta-file.
--
-- *Synopsis*
--
-- #include "glpeta.h"
-- HFILE *create_eta(int n);
--
-- *Description*
--
-- The create_eta routine creates eta-file represented a square matrix
-- of order n. Initially the created eta-file has no terms, therefore
-- formally it corresponds to unity matrix.
--
-- *Returns*
--
-- The create_eta routine returns a pointer to the created eta-file. */

HFILE *create_eta(int n)
{     HFILE *eta;
      if (n < 1)
         fault("create_eta: invalid order");
      eta = umalloc(sizeof(HFILE));
      eta->n = n;
      eta->pool = create_pool(sizeof(HTERM));
      eta->head = eta->tail = NULL;
      return eta;
}

/*----------------------------------------------------------------------
-- app_term - append new eta-term to eta-file.
--
-- *Synopsis*
--
-- #include "glpeta.h"
-- HTERM *app_term(HFILE *eta, int i, int j, double val);
--
-- *Description*
--
-- The app_term routine appends new eta-term to the eta-file, which eta
-- points to. The new eta-term corresponds to the square matrix H(t+1)
-- (where t is the total numbers of terms before appending) that differs
-- from the unity matrix only in one element h[i,j] = val.
--
-- Should note that if i = j and val = 1, or if i != j and val = 0, the
-- eta-term H(t+1) formally is unity matrix. Therefore in this two cases
-- the routine actually doesn't append such eta-term.
--
-- *Returns*
--
-- The app_term routine returns a pointer to the appended eta-term, or
-- NULL, if the eta-term was not appended because of two cases mentioned
-- above. */

HTERM *app_term(HFILE *eta, int i, int j, double val)
{     HTERM *e;
      if (!(1 <= i && i <= eta->n && 1 <= j && j <= eta->n))
         fault("app_term: row or column number out of range");
      if ((i == j && val == 1.0) || (i != j && val == 0.0))
         e = NULL;
      else
      {  e = get_atom(eta->pool);
         e->i = i; e->j = j; e->val = val;
         e->prev = eta->tail; e->next = NULL;
         if (eta->head == NULL)
            eta->head = e;
         else
            eta->tail->next = e;
         eta->tail = e;
      }
      return e;
}

/*----------------------------------------------------------------------
-- h_solve - solve linear system H*x = b using eta-file.
--
-- *Synopsis*
--
-- #include "glpeta.h"
-- double *h_solve(HFILE *eta, double x[]);
--
-- *Description*
--
-- The h_solve routine solves the system H*x = b, where H is the matrix
-- represented by the eta-file which eta points to, x is dense vector of
-- unknowns, b is dense vector of right-hand sides. On entry the array x
-- should contain elements of the vector b in locations x[1], x[2], ...,
-- x[n], where n is the order of the system. On exit this array will
-- contain the vector x in the same locations.
--
-- *Returns*
--
-- The h_solve routine returns a pointer to the array x. */

double *h_solve(HFILE *eta, double x[])
{     HTERM *e;
      for (e = eta->head; e != NULL; e = e->next)
      {  if (e->i == e->j)
         {  if (e->val == 0.0)
               fault("h_solve: singular matrix");
            x[e->i] /= e->val;
         }
         else
            x[e->i] -= e->val * x[e->j];
      }
      return x;
}

/*----------------------------------------------------------------------
-- ht_solve - solve transposed linear system H'*x = b using eta-file.
--
-- *Synopsis*
--
-- #include "glpeta.h"
-- double *ht_solve(HFILE *eta, double x[]);
--
-- *Description*
--
-- The ht_solve routine solves the system H'*x = b, where H' is a matrix
-- transposed to the matrix H which is represented by the eta-file which
-- eta points to, x is dense vector of unknowns, b is dense vector of
-- right-hand sides. On entry the array x should contain elements of the
-- vector b in locations x[1], x[2], ..., x[n], where n is the order of
-- the system. On exit this array will contain the vector x in the same
-- locations.
--
-- *Returns*
--
-- The ht_solve routine returns a pointer to the array x. */

double *ht_solve(HFILE *eta, double x[])
{     HTERM *e;
      for (e = eta->tail; e != NULL; e = e->prev)
      {  if (e->j == e->i)
         {  if (e->val == 0.0)
               fault("ht_solve: singular matrix");
            x[e->j] /= e->val;
         }
         else
            x[e->j] -= e->val * x[e->i];
      }
      return x;
}

/*----------------------------------------------------------------------
-- reset_eta - make eta-file empty.
--
-- *Synopsis*
--
-- #include "glpeta.h"
-- void reset_eta(HFILE *eta);
--
-- *Description*
--
-- The reset_eta routine removes all eta-terms from the eta-file which
-- eta points to. Thus, after this operation the eta-file will formally
-- correspond to the unity matrix.
--
-- Should note that the memory allocated to eta-terms will not be freed.
-- The routine just returns that memory to the memory pool for further
-- usage. */

void reset_eta(HFILE *eta)
{     clear_pool(eta->pool);
      eta->head = eta->tail = NULL;
      return;
}

/*----------------------------------------------------------------------
-- delete_eta - delete eta-file.
--
-- *Synopsis*
--
-- #include "glpeta.h"
-- void delete_eta(HFILE *eta);
--
-- *Description*
--
-- The delete_eta routine deletes the eta-file freeing all memory that
-- was allocated to this object. */

void delete_eta(HFILE *eta)
{     delete_pool(eta->pool);
      ufree(eta);
      return;
}

/* eof */
