// set_relations.h
// Copyright (C) 2023 Mark Bowron
//
// Subset, operator containment, operator equality.
//
// 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 3 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 General Public License for more details.

// Sets are represented by unsigned 32-bit integers with leading zeros.

typedef struct
{
    int *_type;
    int *_x;
    int *_y;
} REL;

REL    *CreateREL(int dim);
void    EraseREL(REL *rel, int dim);
void    FreeREL(REL *rel);
bool    Subset(uint32_t i, uint32_t j);
bool    OpSubset(uint32_t *i, uint32_t *j, int spacesize);
bool    OpEquals(uint32_t *i, uint32_t *j, int spacesize);


REL *CreateREL(int dim)
{
    REL *rel;

    rel = (REL *)malloc(sizeof(REL));
    if (rel==0)
    {
        printf("\nCould not allocate space for rel.\n");
        exit(0);
    }

    rel->_type = (int *)malloc(dim * sizeof(int));
    if (rel->_type==0)
    {
        printf("\nCould not allocate space for rel->_type.\n");
        exit(0);
    }

    rel->_x = (int *)malloc(dim * sizeof(int));
    if (rel->_x==0)
    {
        printf("\nCould not allocate space for rel->_x.\n");
        exit(0);
    }

    rel->_y = (int *)malloc(dim * sizeof(int));
    if (rel->_y==0)
    {
        printf("\nCould not allocate space for rel->_y.\n");
        exit(0);
    }
    
    EraseREL(rel,dim);

    return rel;
}


void EraseREL(REL *rel, int dim)
{
    int j;

    for (j=0; j<dim; j++)
    {
        rel->_type[j] = 0;
        rel->_x[j] = 0;
        rel->_y[j] = 0;
    }
}


void FreeREL(REL *rel)
{
    free(rel->_type);
    free(rel->_x);
    free(rel->_y);
    free(rel);
}


bool Subset(uint32_t i, uint32_t j)     // test whether i is a subset of j
{
    return ((i&j) == i);
}


bool OpSubset(uint32_t *i, uint32_t *j, int spacesize)  // test whether i <= j
{
    int k;

    for (k=0; k<(one<<spacesize); k++) 
        if ((i[k]&j[k]) != i[k]) return false;
    return true;
}


bool OpEquals(uint32_t *i, uint32_t *j, int spacesize)  // test whether i = j
{
    int k;

    for (k=0; k<(one<<spacesize); k++) 
        if (i[k] != j[k]) return false;
    return true;
}
