/*
   File: warshall.c
   Defines Warshalling routines for agflcoder
  
   Copyright 2005, Radboud University of Nijmegen.
  
   This program 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 of the License, or
   (at your option) any later version.
  
   This program 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 Library General Public License for more details.
  
   You should have received a copy of the GNU Library General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

   CVS ID: "$Id: warshall.c,v 1.6 2005/09/06 10:03:16 marcs Exp $"
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include <assert.h>
#include <stdlib.h>
#include <cdl3rts.h>

/* Libabase includes */
#include <abase_error.h>

/* Local include */
#include "warshall.h"

/*
** Global values
*/
static char **matrix;
static int size;

/*
   ACTION initialize matrix (>INT)
*/
void E208_initialize_matrix_INT (value nr_affixes)
{
    int i;

    size = Int(nr_affixes);

    if (size == 0) {
        return;
    }

    /* Get memory */
    matrix = (char **) malloc(size * sizeof(char *));
    if (matrix == NULL)
       abs_fatal ("matrix(initialize_matrix): not enough memory");

    /* Init columns */
    for (i = 0; i < size; i++) {
        matrix[i] = (char *) calloc(size, sizeof(char));
        if (matrix[i] == NULL)
            abs_fatal ("matrix(initialize_matrix): not enough memory");
    }
}


/*
   TEST matrix test (>INT1, >INT2)
*/
int E210_matrix_test_INT_INT(value affix1, value affix2)
{
    assert(Int(affix1) < size);
    assert(Int(affix2) < size);
    return matrix[Int(affix1)][Int(affix2)] != 0;
}


/*
   TEST matrix set(>INT,>INT1)
*/
void E211_matrix_set_INT_INT(value v_INT, value v_INT1)
{
    matrix[Int(v_INT)][Int(v_INT1)] = 1;
}


/*
   ACTION warshall matrix
   Possible optimization: use one bit per affix instead of one char
*/
void E209_warshall_matrix()
{
    int i, j, k;
    for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
            if (matrix[j][i]) {
                for (k = 0; k < size; k++) {
                    if (matrix[i][k]) {
                        matrix[j][k] = 1;
                    }
                }
            }
        }
    }
}
