summaryrefslogblamecommitdiff
path: root/set_bitsets.c
blob: 55786200a580eadce1569d79fd0ccfa8c02c194e (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                      
                 

                   

                                                               
 
                                                                





                                
                                                                 


                         
                                                                                                       
           
                                                                                                         
           
                                                                                                          
           
                                                                                       





                                                                        

 
                          
                     
 
 

                      
                
              



                                       
                                      
                               
                                                  
                   

 
                          

                                 
                                 
                                
                                      




                       
                     


                                      
                       
                                                                             
                                   
         
                                 

                                 
                                             

                                              


                                      
                       
                                                                                    
                                   
         
                                 

                                 
                                             

                                              
                                                                  



                                     
                       
                                                                                  
                                   
         
                                 
                    
                                  
                                                  

                                              
                                                                  

 
                               
                                

 











                                          
                                        


                                                                 
                                  
         
                                              


                                     
                    
                                               
                              
         

                                    



                            
                              

                                 
                                                         

                                                
                    
                      

 


                                        

                                                        









                                                            
                              
                        




                                                                                     

 
                                 




                                                                                  

 


                           
                          

                              
                                  
 
 

                         


                         
                                            

                                                                

             
 
/*
	Projet d'algorithmique et programmation 2013-2014
	(cours de C.Matthieu et J.Stern)
	Alex AUVOLAT, Mendes OULAMARA

	Implémentation des ensembles d'entiers sous forme de bitsets.
	Code sous la juridiction de Mendes OULAMARA.
*/

#include "sets.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define SCOD (unsigned long long)(8*sizeof(unsigned long long))

int nbCells(int n){		//the mathematical ceil function
	if(n == (n/SCOD)*SCOD)
		return n/SCOD;
	else
		return n/SCOD+1;
}

int nb_one(unsigned long long x) {	//the hamming weight of x
	assert(SCOD==64);
	
	//1
	x = (x & 0x5555555555555555) + ((x >> 1) & 0x5555555555555555);		// mask : 0101010101...
	//2
	x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);		// mask : 001100110011...
	//4
	x = (x & 0x0F0F0F0F0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F0F0F0F0F);		// mask : 000011110000....
	//8
	x = (x & 0x00FF00FF00FF00FF) + ((x >> 8) & 0x00FF00FF00FF00FF);		// etc.
	//16
	x = (x & 0x0000FFFF0000FFFF) + ((x >> 16) & 0x0000FFFF0000FFFF);
	//32
	x = (x & 0x00000000FFFFFFFF) + ((x >> 32) & 0x00000000FFFFFFFF);

    return x;
}

int set_size(const set s){
    return *(s.size);
}

set empty_set(int n){
    	assert(n > 0);
	set res;
	int i;
	res.N = n;
	res.size = malloc(sizeof(int));
	*(res.size) = 0;
	int NC = nbCells(n);
	res.tab = malloc((SCOD*NC)/8);
	for(i = 0; i < NC; i++)
	    res.tab[i] = (unsigned long long) (0);
	return res;
}

set copy_set(const set s){
	set res = empty_set(s.N);
	*(res.size) = *(s.size);
	int NC = nbCells(s.N), i;
	for(i = 0; i < NC; i++) 
		res.tab[i] = s.tab[i];
	return res;
}

void delete_set(set a){
	free(a.tab);
	free(a.size);
}

void set_union_ip(set a, const set b){
	if(a.N != b.N){
		printf("Union failed : the sets don't have the same size\n");
		assert(a.N == b.N);
	}
	int NC = nbCells(a.N), i;
	*(a.size)=0;
	for(i = 0; i < NC; i++) {
		a.tab[i] = a.tab[i]|b.tab[i];
		*(a.size) += nb_one(a.tab[i]);
	}
}

void set_inter_ip(set a, const set b){
	if(a.N != b.N){
		printf("Intersection failed : the sets don't have the same size\n");
		assert(a.N == b.N);
	}
	int NC = nbCells(a.N), i;
	*(a.size)=0;
	for(i = 0; i < NC; i++){ 
		a.tab[i] = a.tab[i]&b.tab[i];
		*(a.size) += nb_one(a.tab[i]);
	}
	assert((a.N%SCOD == 0) || (a.tab[NC-1]>>(a.N%SCOD)) == 0);
}


void set_diff_ip(set a, const set b){
	if(a.N != b.N){
		printf("Difference failed : the sets don't have the same size\n");
		assert(a.N == b.N);
	}
	int NC = nbCells(a.N), i;
	*(a.size)=0;
	for(i = 0; i < NC; i++) { 
		a.tab[i] = a.tab[i] & (~b.tab[i]);
		*(a.size) += nb_one(a.tab[i]);
	}
	assert((a.N%SCOD == 0) || (a.tab[NC-1]>>(a.N%SCOD)) == 0);
}

bool is_set_empty(const set s){
    	return (*(s.size) == 0);
}

bool sets_equal(const set a, const set b){
    if(a.N != b.N)
	return false;
    int i, NC = nbCells(a.N);
    for(i = 0; i < NC; i++){
	if(a.tab[i] != b.tab[i])
	    return false;
    }
    assert(*(a.size) == *(b.size));
    return true;
}

inline bool set_mem(int x, const set s){
    unsigned long long ux = x;
	if (!(x < s.N && x >= 0)) {
		printf("Invalid argument for set_mem : %d\n", x);
    	assert(x < s.N && x >= 0);
	}
	return  (s.tab[ux/SCOD]>>(ux%SCOD))&1;
}

int dyadic_val(unsigned long long x){
	if(x == 0) {
		printf("Infinite valuation\n");
		assert(false);
	}
	int i = 0;
	while (((x>>i)&1) == 0) i++;
	return i;
}

int elt_of_set(const set s){
	int N=nbCells(s.N), i;
	for(i=0; i<N; i++)
		if(s.tab[i] != 0)
		    return i*SCOD + dyadic_val(s.tab[i]);

	printf("No element in an empty set!\n");
	dump_set(s);
	assert(false);
}

int elt_of_set_heur(const set s, int h){
    int N=nbCells(s.N), i;

    if(s.tab[h/SCOD]>>(h%SCOD) !=0)
	return h + dyadic_val(s.tab[h/SCOD]>>(h%SCOD)) ;

    for(i=0; i<N; i++)
	if(s.tab[(i+h/SCOD+1)%N] != 0)
	    return i*SCOD+dyadic_val(s.tab[(i+h/SCOD+1)%N]);

	printf("No element in an empty set!\n");
	dump_set(s);
	assert(false);
}

void set_add_ip(int x, set s){
    	assert(x < s.N);
    	unsigned long long ux = x;
    	if(! set_mem(ux, s)){
		s.tab[ux/SCOD] = s.tab[ux/SCOD] | (unsigned long long)(1)<<(ux%SCOD);
		*(s.size) = *(s.size)+1;
	}
}

void set_remove_ip(int x, set s){
    	unsigned long long ux = x;
    if(set_mem(ux, s) ) {
	s.tab[ux/SCOD] = s.tab[ux/SCOD] & (~((unsigned long long)(1)<<(ux%SCOD)));
	*(s.size) = *(s.size)-1;
    }
}

void dump_set(const set s){
    int i=0;
    printf("[");
    for(i=0; i < s.N; i++)
	if(set_mem(i, s))
	    printf(" %d ", i);
    printf("] (%d)\n", *(s.size));
}

set full_set(int n) {
    set r = empty_set(n);
    *(r.size) = n;
    int NC=nbCells(n), i;
    for(i=0; i< NC; i++)
		r.tab[i]=0xFFFFFFFFFFFFFFFF;
	r.tab[NC-1] = ( r.tab[NC-1]>>( (SCOD-(n%SCOD))%SCOD ) );
	assert((n%SCOD == 0) || (r.tab[NC-1]>>(n%SCOD)) == 0);
    return r;
}