/* glpduff.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 "glpduff.h"
#include "glplib.h"

/*----------------------------------------------------------------------
-- create_duff - create Duff's scheme.
--
-- *Synopsis*
--
-- #include "glpduff.h"
-- DUFF *create_duff(int n, int maxlen);
--
-- *Description*
--
-- The create_duff routine creates a scheme that can contain up to n
-- objects, where the length of each object changes from 0 to maxlen.
-- The created scheme initially contains no objects.
--
-- *Returns*
--
-- The create_duff routine returns a pointer to the created scheme. */

DUFF *create_duff(int n, int maxlen)
{     DUFF *duff;
      int k, len;
      if (n < 1)
         fault("create_duff: invalid number of objects");
      if (maxlen < 0)
         fault("create_duff: invalid maximal length of object");
      duff = umalloc(sizeof(DUFF));
      duff->n = n;
      duff->maxlen = maxlen;
      duff->len = ucalloc(1+n, sizeof(int));
      duff->head = ucalloc(1+maxlen, sizeof(int));
      duff->prev = ucalloc(1+n, sizeof(int));
      duff->next = ucalloc(1+n, sizeof(int));
      for (k = 1; k <= duff->n; k++) duff->len[k] = -1;
      for (len = 0; len <= duff->maxlen; len++) duff->head[len] = 0;
      return duff;
}

/*----------------------------------------------------------------------
-- include_obj - include object to Duff's scheme.
--
-- *Synopsis*
--
-- #include "glpduff.h"
-- void include_obj(DUFF *duff, int k, int len);
--
-- *Description*
--
-- The include_obj routine includes an object to the Duff's scheme. The
-- parameter k is the number of the included object, the parameter len
-- is the length of the included object. The object should be not in the
-- scheme before inclusion. */

void include_obj(DUFF *duff, int k, int len)
{     if (!(1 <= k && k <= duff->n))
         fault("include_obj: invalid object number");
      if (!(0 <= len && len <= duff->maxlen))
         fault("include_obj: invalid object length");
      if (duff->len[k] >= 0)
         fault("include_obj: object is already in the scheme");
      duff->len[k] = len;
      duff->prev[k] = 0;
      duff->next[k] = duff->head[len];
      if (duff->head[len] == 0)
         /* nop */;
      else
         duff->prev[duff->head[len]] = k;
      duff->head[len] = k;
      return;
}

/*----------------------------------------------------------------------
-- exclude_obj - exclude object from Duff's scheme.
--
-- *Synopsis*
--
-- #include "glpduff.h"
-- void exclude_obj(DUFF *duff, int k);
--
-- *Description*
--
-- The exclude_obj routine excludes an object from the Duff's scheme.
-- The parameter k is the number of the excluded object. The object
-- should be in the scheme before exclusion. */

void exclude_obj(DUFF *duff, int k)
{     int len;
      if (!(1 <= k && k <= duff->n))
         fault("exclude_obj: invalid object number");
      len = duff->len[k];
      if (len < 0)
         fault("exclude_obj: object is not in the scheme");
      duff->len[k] = -1;
      if (duff->prev[k] == 0)
         duff->head[len] = duff->next[k];
      else
         duff->next[duff->prev[k]] = duff->next[k];
      if (duff->next[k] == 0)
         /* nop */;
      else
         duff->prev[duff->next[k]] = duff->prev[k];
      return;
}

/*----------------------------------------------------------------------
-- reset_duff - clear Duff's scheme.
--
-- *Synopsis*
--
-- #include "glpduff.h"
-- void reset_duff(DUFF *duff);
--
-- *Description*
--
-- The reset_duff routine clears the Duff's scheme excluding from it
-- all objects. */

void reset_duff(DUFF *duff)
{     int k, len;
      for (k = 1; k <= duff->n; k++) duff->len[k] = -1;
      for (len = 0; len <= duff->maxlen; len++) duff->head[len] = 0;
      return;
}

/*----------------------------------------------------------------------
-- delete_duff - delete Duff's scheme.
--
-- *Synopsis*
--
-- #include "glpduff.h"
-- void delete_duff(DUFF *duff);
--
-- *Description*
--
-- The delete_duff routine deletes the Duff's scheme freeing all memory
-- allocated to this object. */

void delete_duff(DUFF *duff)
{     ufree(duff->len);
      ufree(duff->head);
      ufree(duff->prev);
      ufree(duff->next);
      ufree(duff);
      return;
}

/* eof */
