/** Set Operations Module
 * This module contains the operations on sets. It is used when we use the set model.
*  The operations takes place on the bdd level. Every bdd in a set model, is a set and hence these functions operate on sets (bdds).
*/

#include "set.h"
#include <bdd.h>


/**  This function is the set uinon between two sets. The returned set contains both the elements of the unioned sets.
 */

bdd setUnion(const bdd &s1, const bdd &s2){
 bdd u;
 // the following commented code is equivalent to the one liner.
	//if (s1 == bddfalse)
 //   return s2;
 //else if (s2 == bddfalse)
 //   return s1;
 //else
    u = s1 | s2;
 return u;
 
}


/** This funtions the set intersection between two sets. The returned set contains the elements that are shared in the original sets.
 */
bdd setIntersection(const bdd &s1, const bdd &s2){ 
 bdd u;
 u = s1 & s2;
	return u;
 
}

/** This function is the xor between two sets. The returned set contains all the elements in both the sets except the common ones.
 * 
*/
bdd setXOR(bdd &s1, bdd &s2){
 bdd u;
 u = s1 ^ s2;
 return u;
}


/** This function checks if an element is is a member in a set. It returns true or false. 
 */ 
bool existsInSet(bdd feature, const bdd &family){ 
   if ((feature | family) == family)
   { 
      return true;
   }
   else
   { 
      return false;
   }

}

bool setIsMember(bdd feature, const bdd &family){ 
   bdd temp;
   temp = (feature & family); // remove this
   if ((feature & family) == family)
   { 
      return true;
   }
   else
   { 
      return false;
   }

}

/** This function returns the complement set of a given set. 
 */
 
bdd setComplement(bdd &family){
	
	return bdd_not(family);
	
}

/** Given an element, feature, this function inserts it into a set, family. 
*/ 
void setInsert(bdd feature, bdd &family){
	
	family = feature | family;
}

/** Given an element, feature, this function removes it from a given set, family.
 */ 
void setRemove(bdd feature, bdd &family){
	
	family = bdd_exist(family, feature);
}
 
/** This function checks if a given set, family, is empty. If so, it returns true and false otherwise.
*/
bool setIsEmpty(bdd family){
	
	if (family == bdd_true())
	   return true;
	else
	   return false;
}

bool setEquals(const bdd &s1,const bdd &s2)
{
    if (setIsMember(s1, s2) == setIsMember(s2,s1) ) return true;
}

/** This function displays the content of a given set, family in this format: e.g.: {1,3,9}, where 1,3,9 are the elements in the set.
 */
void setEnumerate(const bdd &family){
					bool first = true;
     cout << "{ ";
     for (int i = 1; i <= levels; i++)  // check 0 if need onebdd to be shown
     {
									//if (setIsMember(bdd_ithvar(i), family))
								
									if (existsInSet(bdd_ithvar(i), family))
											 {   
																if (first)
																			{
																					//cout << i ;
																					cout << names[i];
																					first = false;
																			}
																else
																			{
																				//cout << ", " << i ;
																					cout << ", " << names[i];
																			}
										  }


					}

	 
	 cout << " }" << endl;
}


