// set_operators.h
// Copyright (C) 2023 Mark Bowron

// Complement, closure, interior, boundary, border.

// 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.


uint32_t    Comp(uint32_t set, int spacesize);
uint32_t    Clos(uint32_t set, int spacesize, uint32_t *point_closures);
uint32_t    Int(uint32_t set, int spacesize, uint32_t *point_closures);
uint32_t    Bdry(uint32_t set, int spacesize, uint32_t *point_closures);
uint32_t    Bord(uint32_t set, int spacesize, uint32_t *point_closures);
void        IntToBits(uint32_t set, int spacesize, char *bits);

// These constants are global.

const uint32_t  one = 1;
const uint32_t  max = 31;   // Space cardinalities 1-31 are allowed.
const int canonical_psi_number[43] = {1,2,3,5,6,7,8,9,10,11,12,13,21,23,24,26,
                                      27,28,30,31,32,34,35,38,39,40,41,42,45,
                                      46,49,51,53,54,57,58,59,61,62,64,65,68,69};
const int psi_to_phi[71] = {0,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3,4,5,6,6,6,
                            6,6,6,6,6,6,7,8,9,9,10,10,11,12,13,14,14,15,15,16,16,
                            17,17,18,19,20,21,22,22,23,23,24,25,25,25,25,26,27,28,
                            28,29,29,30,30,30};
const int k_num[71] = {0,14,14,14,14,14,14,12,12,12,12,12,12,12,12,12,12,12,12,12,
                       12,12,12,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
                       8,8,8,8,8,8,8,8,8,8,8,6,6,6,6,6,6,6,6,6,6,4,4,4,4,4,4,4,2,2,2};
const int kf_num[71] = {0,34,32,32,32,30,28,30,28,28,26,26,24,22,30,28,28,26,26,24,22,
                        28,28,26,24,24,22,22,20,20,18,18,24,24,22,14,22,14,22,20,16,16,
                        10,16,10,16,10,16,10,14,14,12,12,10,6,10,6,10,10,6,6,4,8,8,8,4,
                        8,4,4,2,2};
const char *ge_monoid[] = {"","D","P","EO","ED","OU","GE","KD"};
const char *kfg_type[] = {"","D","P","EO 1","ED 1","OU 1","GE 1","KD 1",
                                     "EO 2","ED 2","OU 2","GE 2","KD 2"};

// spaces[n] is the number of nonhomeomorphic topological spaces on n points.
// We know we have exactly this many lines of input.

const int spaces[12] = {1,1,3,9,33,139,718,4535,35979,363083,
                                    4717687,79501654};


uint32_t Comp(uint32_t set, int spacesize)  // returns complement of set
{
// The parentheses around the difference are to avoid exceeding the maximum value
// of uint32_t while the operand is being evaluated.

    return ~((one<<max) + ((one<<max)-(one<<(uint32_t)spacesize)) + set);
}


uint32_t Clos(uint32_t set, int spacesize, uint32_t *point_closures)
{
    uint32_t    j = 0;
    int         i;

    for (i=0; i<spacesize; i++)
    {
        if (set & (one<<(uint32_t)i)) j = j | point_closures[i];
    }
    return j;
}


uint32_t Int(uint32_t set, int spacesize, uint32_t *point_closures)
{
    uint32_t    i;

    i = Comp(set, spacesize);
    i = Clos(i, spacesize, point_closures);
    return Comp(i, spacesize);
}


uint32_t Bdry(uint32_t set, int spacesize, uint32_t *point_closures)
{
    uint32_t    i, j;

    i = Clos(set, spacesize, point_closures);
    j = Comp(set, spacesize);
    j = Clos(j, spacesize, point_closures);
    return i & j;
}


uint32_t Bord(uint32_t set, int spacesize, uint32_t *point_closures)
{
    return set & Bdry(set, spacesize, point_closures);
}


void IntToBits(uint32_t set, int spacesize, char *bits)
{
    int j;

    for (j=0; j<spacesize; j++)
    {
        if (set & (one<<j)) bits[j] = '1';
        else bits[j] = '0';
    }
    bits[spacesize] = '\0';
}
