//--------------------------------------------------------
//   F i s i e r u l       m u l t i m e . c
//--------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "multime.h"

MULTIME newSet(int n)
{
//alocarea spaţiului necesar informatiilor despre multime
    MULTIME e=(MULTIME) malloc(sizeof(Multime));
    if (e!=NULL)  //daca alocarea a avut succes
    {
        char *q;
        // se aloca spatiul pentru vectorul caracteristic
        q=(char *) malloc((n+7)/8);
        // daca alocarea nu poate fi realizata
        if (q==NULL)
        {
            // se elibereaza spatiul deja alocat
            free (e);
// multimea nu poate fi initializata
            return NULL;
        }
        // se completeaza campurile corespunzatoare
        e->n = n;
        e->pv = q;
        // se initializeaza vectorul caracteristic cu 0
        for(n=(n+7)/8 -1; n>=0; n--)
            q[n]=0;
    }
    return e;
}

MULTIME insert(MULTIME e, DATA x)
{
// conversia de la tipul DATA la tipul int
    int ix=(int)x;
// testarea nedepasirii limitelor
    if (ix>=0 && ix<e->n)
        // setarea bitului ix din vect. caracteristic la valoarea 1
        // prin operatia de SAU pe biti intre octetul ix/8
        // si o masca ce contine 1 doar pe pozitia ix%8
        // considerata de la dreapta spre stanga
        e->pv[ix/8] |= 1<< ix%8;
    return e;
}

LOGIC member(MULTIME e, DATA x)
{
// conversia de la tipul DATA la tipul int
    int ix=(int)x;
// testarea nedepasirii limitelor
    if (ix>=0 && ix<e->n)
        // daca bitul ix din vectorul caracteristic are valoarea 1
        // expresia de mai jos returneaza o valoare diferita de 0
        // altfel returneaza valoarea 0
        return e->pv[ix/8]  &  1 << ix%8;
// in caz de depasire a limitelor corespunzatoare
// elementul x nu apartine multimii
    return FALS;
}
MULTIME Delete(MULTIME e, DATA x)
{
    int ix=(int)x;
    e->pv[ix/8] &= ~( 1 << ix%8 );
    return e;
}

int cardinal(MULTIME e)
{
    return e->n;
}

MULTIME Union(MULTIME A,MULTIME B)
{
    MULTIME R;
    int i;
    if(A==NULL || B==NULL)
    {
        printf("\nErr: cel putin o multime este neinitiaizata.");
        return NULL;
    }
    if(A->n != B->n)
    {
        printf("\nEroare: universuri de cardinali diferiti");
        return NULL;
    }
    if((R=newSet(A->n))==NULL) return NULL;
    for(i=0; i<(A->n+7)/8; i++)
        R->pv[i] = A->pv[i] | B->pv[i];
    return R;
}

void destroySet(MULTIME e)
{
    if(e!=NULL)
    {
        free(e->pv);
        free(e);
    }
}

LOGIC isEmptySet(MULTIME e)
{
    int i;
    for(i=0; i<(e->n+7)/8; i++)
        if(e->pv[i] !=0) return FALS;
    return ADEVARAT;
}

char *conv_multime_sir(MULTIME e, char *zona)
{
    int i,j;
    char oct;
    if(e==NULL) return "Multime neintializata";
    if(isEmptySet(e))
        return "vida";
    else
    {
        strcpy(zona,"{");
        for(i=0; i<(e->n+7)/8; i++)
        {
            oct=e->pv[i];
            for(j=0; j<8; j++)
            {
                if((oct & 1)!=0)
                    sprintf(zona+strlen(zona), FORMAT",",i*8+j);
                oct>>=1;
            }
        }
        sprintf(zona+strlen(zona)-1,"}");
        return zona;
    }
}

