https://github.com/shader-slang/slang
Raw File
Tip revision: 4f979d74acf2800d7bd2b38155d2bdc47b57d54b authored by Tim Foley on 25 September 2018, 02:17:12 UTC
Fixes around atomic operations (#652)
Tip revision: 4f979d7
int-set.h
#ifndef BIT_VECTOR_INT_SET_H
#define BIT_VECTOR_INT_SET_H

#include "list.h"
#include "slang-math.h"
#include "common.h"
#include "exception.h"

#include <memory.h>

namespace Slang
{
	class IntSet
	{
	private:
		List<int> buffer;
	public:
		IntSet()
		{}
		IntSet(const IntSet & other)
		{
			buffer = other.buffer;
		}
		IntSet(IntSet && other)
		{
			*this = (_Move(other));
		}
		IntSet & operator = (IntSet && other)
		{
			buffer = _Move(other.buffer);
			return *this;
		}
		IntSet & operator = (const IntSet & other)
		{
			buffer = other.buffer;
			return *this;
		}
		int GetHashCode()
		{
			int rs = 0;
			for (auto val : buffer)
				rs ^= val;
			return rs;
		}
		IntSet(int maxVal)
		{
			SetMax(maxVal);
		}
		UInt Size() const
		{
			return buffer.Count()*32;
		}
		void SetMax(int val)
		{
			Resize(val);
			Clear();
		}
		void SetAll()
		{
			for (UInt i = 0; i<buffer.Count(); i++)
				buffer[i] = 0xFFFFFFFF;
		}
		void Resize(UInt size)
		{
			UInt oldBufferSize = buffer.Count();
			buffer.SetSize((size+31)>>5);
			if (buffer.Count() > oldBufferSize)
				memset(buffer.Buffer()+oldBufferSize, 0, (buffer.Count()-oldBufferSize) * sizeof(int));
		}
		void Clear()
		{
			for (UInt i = 0; i<buffer.Count(); i++)
				buffer[i] = 0;
		}
		void Add(UInt val)
		{
			UInt id = val>>5;
			if (id < buffer.Count())
				buffer[id] |= (1<<(val&31));
			else
			{
				UInt oldSize = buffer.Count();
				buffer.SetSize(id+1);
				memset(buffer.Buffer() + oldSize, 0, (buffer.Count()-oldSize)*sizeof(int));
				buffer[id] |= (1<<(val&31));
			}
		}
		void Remove(UInt val)
		{
			if ((val>>5) < buffer.Count())
				buffer[(val>>5)] &= ~(1<<(val&31));
		}
		bool Contains(UInt val) const
		{
			if ((val>>5) >= buffer.Count())
				return false;
			return (buffer[(val>>5)] & (1<<(val&31))) != 0;
		}
		void UnionWith(const IntSet & set)
		{
			for (UInt i = 0; i<Math::Min(set.buffer.Count(), buffer.Count()); i++)
			{
				buffer[i] |= set.buffer[i];
			}
			if (set.buffer.Count() > buffer.Count())
				buffer.AddRange(set.buffer.Buffer()+buffer.Count(), set.buffer.Count()-buffer.Count());
		}
		bool operator == (const IntSet & set)
		{
			if (buffer.Count() != set.buffer.Count())
				return false;
			for (UInt i = 0; i<buffer.Count(); i++)
				if (buffer[i] != set.buffer[i])
					return false;
			return true;
		}
		bool operator != (const IntSet & set)
		{
			return !(*this == set);
		}
		void IntersectWith(const IntSet & set)
		{
			if (set.buffer.Count() < buffer.Count())
				memset(buffer.Buffer() + set.buffer.Count(), 0, (buffer.Count()-set.buffer.Count())*sizeof(int));
			for (UInt i = 0; i<Math::Min(set.buffer.Count(), buffer.Count()); i++)
			{
				buffer[i] &= set.buffer[i];
			}
		}
		static void Union(IntSet & rs, const IntSet & set1, const IntSet & set2)
		{
			rs.buffer.SetSize(Math::Max(set1.buffer.Count(), set2.buffer.Count()));
			rs.Clear();
			for (UInt i = 0; i<set1.buffer.Count(); i++)
				rs.buffer[i] |= set1.buffer[i];
			for (UInt i = 0; i<set2.buffer.Count(); i++)
				rs.buffer[i] |= set2.buffer[i];
		}
		static void Intersect(IntSet & rs, const IntSet & set1, const IntSet & set2)
		{
			rs.buffer.SetSize(Math::Min(set1.buffer.Count(), set2.buffer.Count()));
			for (UInt i = 0; i<rs.buffer.Count(); i++)
				rs.buffer[i] = set1.buffer[i] & set2.buffer[i];
		}
		static void Subtract(IntSet & rs, const IntSet & set1, const IntSet & set2)
		{
			rs.buffer.SetSize(set1.buffer.Count());
			for (UInt i = 0; i<Math::Min(set1.buffer.Count(), set2.buffer.Count()); i++)
				rs.buffer[i] = set1.buffer[i] & (~set2.buffer[i]);
		}
		static bool HasIntersection(const IntSet & set1, const IntSet & set2)
		{
			for (UInt i = 0; i<Math::Min(set1.buffer.Count(), set2.buffer.Count()); i++)
			{
				if (set1.buffer[i] & set2.buffer[i])
					return true;
			}
			return false;
		}
	};
}

#endif
back to top