/***************************************************
* unit:    sets           release 0.12             *
* purpose: general manipulation with binary arrays *
* Licency: GPL or LGPL                             *
* Copyright: (c) 1998-2024 Jaroslav Fojtik         *
****************************************************/
#ifndef __sets
#define __sets

#include <limits.h>

#include "typedfs.h"
#ifdef __UniX
 #include <unistd.h>
#endif

#define SETS_VERSION (0x100*0 | 12)

#ifndef __Common_H_INCLUDED
  #include "common.h"
#endif


#ifndef No_Memory
 #define No_Memory   0x1
#endif
#ifndef Bad_Bounds
 #define Bad_Bounds   0x2
#endif
#define Bad_MaxBound 0x3
#define Bad_MinBound 0x4
#define Wrong_Set    0x5

#ifndef IN
 #define IN %
#else
 #undef IN
 #define IN %
#endif

#define TrickInterval INT_MIN
#define ___ ,TrickInterval,


class set;
class temp_set;

// Main definition part of Class set
class set  {
protected:  uint16_t *data;
            int MinElement,MaxElement;
public:
            void resize(int MinElement, int MaxElement);
            set(int Min, int Max);
public:
            set(void);
            set(int number);
            set(const set & s);
            set(temp_set &s);
            set(const int *Array, int Size);
            ~set(void)                          {erase(*this);};

            set &operator=(int number);
            set &operator=(const set &s);
            set &operator=(temp_set &s);

            int operator[](int i) const;
            friend int operator IN(int i,const set &s) {return(s[i]);};
            int operator IN (const set &s) const;

            int operator==(const set &s) const;
            int operator!=(const set &s) const  {return(!(*this==s));}
            int operator>(const set &s) const           {return(Card(*this)>Card(s));}
            int operator>=(const set &s) const  {return(Card(*this)>=Card(s));}
            int operator<(const set &s) const           {return(Card(*this)<Card(s));}
            int operator<=(const set &s) const  {return(Card(*this)<=Card(s));}

            friend temp_set operator+(const set & s1, const set & s2);
            friend temp_set operator+(const set & s1, int number);
            friend temp_set operator+(int number, const set & s2);
            friend temp_set operator|(const set & s1, const set & s2);
            friend temp_set operator|(const set & s1, int number);
            friend temp_set operator|(int number, const set & s2);
            friend temp_set operator-(const set & s1, const set & s2);
            friend temp_set operator-(const set & s1, int number);
            friend temp_set operator-(int number, const set & s2);
            friend temp_set operator&(const set & s1, const set & s2);
            friend temp_set operator&(const set & s1, int number);
            friend temp_set operator&(int number, const set & s2);
            friend temp_set operator^(const set & s1, const set & s2);
            set &operator+=(int number);
            set &operator+=(const set & s2);
            set &operator|=(int number);
            set &operator|=(const set & s2);
            set &operator-=(int number);
            set &operator-=(const set & s2);
            set &operator&=(int number);
            set &operator&=(const set & s2);
            set &operator^=(int number);
            set &operator^=(const set & s2);

            int isEmpty(void) const;

            friend char *set2str(char *str,const set &s);
            friend temp_set str2set(const char *str);
            friend int Card(const set &s);
            friend int EmptyCheck(const set &s) {return s.isEmpty();};

            friend void erase(set &s);
            friend int check(set &s);

            friend class temp_set;
            };

char *set2str(char *str,const set &s);
temp_set str2set(const char *str);


//Internal speedup class - do not use it unless you know what you are doing!
class temp_set:public set
        {
public: temp_set(int Min,int Max):set(Min,Max){};
        temp_set(void)  {};
        temp_set(int number):set(number)        {};
        temp_set(const set & s):set(s)          {};
        temp_set(temp_set & s):set(s)           {};
        };

inline temp_set operator+(int number, const set & s2) {return s2+number;}
inline temp_set operator|(const set & s1, const set & s2) {return s1 + s2;}
inline temp_set operator|(const set & s1, int number) {return s1 + number;}
inline temp_set operator|(int number, const set & s2) {return s2+number;}
inline temp_set operator&(int number, const set & s2) {return s2 & number;}
inline temp_set operator^(const set & s1, int number) {temp_set tmp(s1);tmp^=number;return tmp;}
inline temp_set operator^(int number, const set & s2) {temp_set tmp(s2);tmp^=number;return tmp;}
inline set &set::operator+=(const set & s2)     {return *this=*this+s2;}
inline set &set::operator|=(int number)         {return *this=*this+number;}
inline set &set::operator|=(const set & s2)     {return *this=*this+s2;}
inline set &set::operator-=(const set & s2)     {return *this=*this-s2;}
inline set &set::operator&=(const set & s2)     {return *this=*this&s2;}
inline set &set::operator^=(const set & s2)     {return *this=*this^s2;}


#ifdef Streams
 #ifdef IOSTREAM_H_ONLY
  #include<iostream.h>
  ostream &operator<<(ostream & xout, const set & s);
 #else
  #include<iostream>
  std::ostream &operator<<(std::ostream &xout, const set &s);
  //istream &operator>>(istream &, set &l);
 #endif
#endif


#ifndef min
 #define min(value1,value2) ((value1 < value2) ? value1 : value2)
#endif
#ifndef max
 #define max(value1,value2) ((value1 > value2) ? value1 : value2)
#endif


#endif	// __sets
