// main.c
// Copyright (C) 2023 Mark Bowron

// Find all intersections of phi- and psi-numbers.

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


#include    <stdio.h>
#include    <stdlib.h>
#include    <inttypes.h>
#include    <stdbool.h>
#include    <string.h>
#include    "set_operators.h"
#include    "set_families.h"
#include    "set_relations.h"
#include    "collapses.h"
#include    "phi-numbers.h"
#include    "psi-numbers.h"


int main(int argc, const char * argv[])
{
    int     j, k, l, m;
    int  ***phi, ***psi, **phi_equals, **psi_equals;

    KZenum  kz_key = {0,1,2,3,4,5,6};
    KZenum *kz = &kz_key;
    KFenum  kf_key = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
                    20,21,22,23,24,25,26,27,28,29,30,31,32,33};
    KFenum *kf = &kf_key;


    phi = (int ***)malloc(31 * sizeof(int **));
    if (phi==0)
    {
        printf("\nCould not allocate space for phi.\n");
        exit(0);
    }
    for (j=0; j<31; j++)
    {
        phi[j] = (int **)malloc(7 * sizeof(int *));
        if (phi[j]==0)
        {
            printf("\nCould not allocate space for phi[%d].\n", j);
            exit(0);
        }
        for (k=0; k<7; k++)
        {
            phi[j][k] = (int *)malloc(7 * sizeof(int));
            if (phi[j][k]==0)
            {
                printf("\nCould not allocate space for phi[%d][%d].\n", j, k);
                exit(0);
            }
        }
    }
    phi_equals = (int **)malloc(7 * sizeof(int *));
    if (phi_equals==0)
    {
        printf("\nCould not allocate space for phi_equals.\n");
        exit(0);
    }
    for (j=0; j<7; j++)
    {
        phi_equals[j] = (int *)malloc(7 * sizeof(int));
        if (phi_equals[j]==0)
        {
            printf("\nCould not allocate space for phi_equals[%d].\n", j);
            exit(0);
        }
        for (k=0; k<7; k++) phi_equals[j][k] = 0;
    }
    for (j=0; j<31; j++)
        for (k=0; k<7; k++)
            memcpy(phi[j][k],phi_numbers[j][k],sizeof(phi_numbers[j][k]));

    psi = (int ***)malloc(71 * sizeof(int **));
    if (psi==0)
    {
        printf("\nCould not allocate space for psi.\n");
        exit(0);
    }
    for (j=0; j<71; j++)
    {
        psi[j] = (int **)malloc(34 * sizeof(int *));
        if (psi[j]==0)
        {
            printf("\nCould not allocate space for psi[%d].\n", j);
            exit(0);
        }
        for (k=0; k<34; k++)
        {
            psi[j][k] = (int *)malloc(34 * sizeof(int));
            if (psi[j][k]==0)
            {
                printf("\nCould not allocate space for psi[%d][%d].\n", j, k);
                exit(0);
            }
        }
    }
    psi_equals = (int **)malloc(34 * sizeof(int *));
    if (psi_equals==0)
    {
        printf("\nCould not allocate space for psi_equals.\n");
        exit(0);
    }
    for (j=0; j<34; j++)
    {
        psi_equals[j] = (int *)malloc(34 * sizeof(int));
        if (psi_equals[j]==0)
        {
            printf("\nCould not allocate space for psi_equals[%d].\n", j);
            exit(0);
        }
        for (k=0; k<34; k++) psi_equals[j][k] = 0;
    }
    for (j=0; j<71; j++)
        for (k=0; k<34; k++)
            memcpy(psi[j][k],psi_numbers[j][k],sizeof(psi_numbers[j][k]));

// phi[n][x][y] = 1 iff the xth and yth sets in the canonical order on KZ(A) are equal
// and psi[n][x][y] is defined similarly.
//
// We intersect all phi[] matrices (respectively, psi[] matrices) pairwise and compute
// the phi-numbers (respectively, psi-numbers) of these intersections.

// Compute all nontrivial phi-number intersections.

    for (j=2; j<31; j++)
    {
        for (k=1; k<j; k++)
        {

// Store the intersection of phi[j] and phi[k] in phi_equals[j][k].

            for (l=0; l<7; l++)
                for (m=0; m<7; m++)
                {
                    if (phi[j][l][m]*phi[k][l][m]) phi_equals[l][m] = 1;
                    else phi_equals[l][m] = 0;
                }

// Print the phi-number of phi_equals.

            printf("%d\t", PhiArray(phi_equals,kz));
        }
        printf("\n");
    }

    printf("\n");

// Compute all nontrivial intersections of psi-numbers <= 30.

    for (j=2; j<30; j++)
    {
        for (k=2; k<j; k++) printf("\t");
        for (k=j+1; k<31; k++)
        {

// Store the intersection of psi[j] and psi[k] in psi_equals[j][k].

            for (l=0; l<34; l++)
                for (m=0; m<34; m++)
                {
                    if (psi[j][l][m]*psi[k][l][m]) psi_equals[l][m] = 1;
                    else psi_equals[l][m] = 0;
                }

// Print the psi-number of psi_equals.

            printf("%d\t", PsiArray(psi_equals,kf));
        }
        printf("\n");
    }

    printf("\n");

    for (j=0; j<31; j++)
    {
        for (k=0; k<7; k++) free(phi[j][k]);
        free(phi[j]);
    }
    free(phi);
    for (j=0; j<7; j++) free(phi_equals[j]);
    free(phi_equals);
    for (j=0; j<71; j++)
    {
        for (k=0; k<34; k++) free(psi[j][k]);
        free(psi[j]);
    }
    free(psi);
    for (j=0; j<34; j++) free(psi_equals[j]);
    free(psi_equals);
}
