/*
   A simple implementation of a set of numbers 
   similar to what's available in Pascal
   No more than 400 numbers in the set as it is
   currently configured.

   Author: Larry Morell
   Revision history
   Ancient days -- implemented using strings
   3/14/06  -- completely redone using a bitmap
*/

using namespace std;
#include <iostream>
#include <string>
#include "IntSets.h"
#include <string>
#include <assert.h>

/* Private routines */
struct IntSet::position IntSet::pos(int n) {  // Given n, return its position
   struct position p;
   p.pos = n / 32;
   p.offset = n % 32;
   return p;
}
void IntSet::set (int n){ //  Set position associated with n to true
   //cout << "n is " << n << endl;
   assert ((0 <=n) && (n/32 < MAX));
   struct position p;
   p = pos(n);
   info[p.pos] = info[p.pos] | (1 << p.offset);
   //cout << "Position " << p.pos  << " "  << p.offset  << " "
        //<< (int) info[p.pos]
        //<< endl;; 
}

void IntSet::reset (int n){ //  Set position associated with n to false
   struct position p;
   p = pos(n);
   info[p.pos] = info[p.pos] ^ (255- (1 << p.offset));
}

bool IntSet::isSet (int n){  // true iff position assoc with n is set
   struct position p;
   p = pos(n);
   return info[p.pos] & (1 << p.offset); 
}
bool IntSet::isSet (struct position p){  // true iff position assoc with p is set
   return info[p.pos] & (1 << p.offset); 
}

/* public routines */

/* Constructors */ 
IntSet::IntSet() // create empty set
{
   for (int i=0; i < MAX; i ++) info[i] = 0; // all zero bits
}

IntSet::IntSet(string s) // create set consisting of int's from s
{
   //cout << "initializing set to " << s << endl;
   for (int i=0; i < MAX; i ++) info[i] = 0; // all zero bits
   for (int i=0; i < s.length(); i++) {
      set (s[i]);  
   }
}

IntSet::IntSet(int s) // create set consisting of int's from s
{
   for (int i=0; i < MAX; i ++) info[i] = 0; // all zero bits
   set (s);  
   
}

IntSet IntSet::operator+ (IntSet t) // union
{
  IntSet *result = new IntSet();
  for (int i=0; i < MAX; i++) 
     result->info[i] = info[i];
  return *result;
}

/* Overloaded operations */
IntSet IntSet::operator+ (int t) // append
{
  IntSet *result = new IntSet(*this);
  //cout << "Setting " << t << endl;
  result -> set(t);
  return *result;
}

IntSet IntSet::operator- (IntSet t) // set diff s - t
{
/*
  cout << "Entering operator-:"  << endl;
  displayln();
  t.displayln();
*/
  IntSet *result = new IntSet(*this);
  for (int i=0; i < MAX; i++) {
/*
     cout << "Or-ing: " 
          << (int) result -> info[i] 
          << " "
          << (int)  t.info[i] << endl;
*/
     result->info[i] ^=  t.info[i];
  }

  return *result;
}

IntSet IntSet::operator- (int t) // append
{
  IntSet s(t);
  return *this - s;
}

IntSet IntSet::operator* (IntSet t) // intersection
{
  IntSet *result = new IntSet();
  for (int i=0; i < MAX; i++) {
     result->info[i] &=  t.info[i];
  }
  return *result;
}

void IntSet::display ()  // display the set
{
   bool commaNeeded = false;
   cout << "{";
   for (int i=0; i < MAX; i++) {
      //cout << i << ":";
      for (int j=0; j < 32; j++) {
         if (info[i] & (1 << j)) {
             if (commaNeeded)  cout << ", ";
             else commaNeeded = true;
             cout << i*32 + j ;
            // cout << 1;
         }
         else ;
            // cout << 0;
      }
   }
   cout << "}" ;
}

void IntSet::displayln ()  // display the set
{
   display();
   cout << endl;
}

int IntSet::contains (int c)         // is c in the set?
{
   return (isSet(c));
}


