Exemplo n.º 1
0
 void Resize()
 {
     Resize(HashHelpers.ExpandPrime(count));
 }
 private void Resize()
 {
     Resize(HashHelpers.ExpandPrime(count), false);
 }
Exemplo n.º 3
0
        bool AddValue(T key, ref W value)
        {
//get the hash and bucket index
            int hash        = key.GetHashCode() & int.MaxValue;
            int bucketIndex = hash % _buckets.Length;

            //buckets value -1 means it's empty
            var valueIndex = GetBucketIndex(_buckets[bucketIndex]);

            if (valueIndex == -1)
            {
                //create the infonode at the last position and fill it with the relevant information
                _valuesInfo[_freeValueCellIndex] = new Node(ref key, hash);
            }
            else
            {
                int currentValueIndex = valueIndex;
                do
                {
                    //must check if the key already exists in the dictionary
                    //for some reason this is way faster they use Comparer<T>.default, should investigate
                    if (_valuesInfo[currentValueIndex].hashcode == hash &&
                        _valuesInfo[currentValueIndex].key.CompareTo(key) == 0)
                    {
                        return(false);
                    }

                    currentValueIndex = _valuesInfo[currentValueIndex].previous;
                }while (currentValueIndex != -1);

                //oops collision!
                _collisions++;
                //create a new one that points to the existing one
                //new one prev = the first in the bucket
                _valuesInfo[_freeValueCellIndex] =
                    new Node(ref key, hash, valueIndex);
                //the first in the bucket next = new one
                _valuesInfo[valueIndex].next =
                    (int)_freeValueCellIndex;
            }

            //item with this bucketIndex will point to the last value created
            _buckets[bucketIndex] = _freeValueCellIndex + 1;

            _values[_freeValueCellIndex] = value;

            if (++_freeValueCellIndex == _values.Length)
            {
                Array.Resize(ref _values,
                             HashHelpers.ExpandPrime((int)_freeValueCellIndex));
                Array.Resize(ref _valuesInfo,
                             HashHelpers.ExpandPrime((int)_freeValueCellIndex));
            }

            //too many collisions?
            if (_collisions > _buckets.Length)
            {
                //we need more space and less collisions
                _buckets = new int[HashHelpers.ExpandPrime(_collisions)];

                _collisions = 0;

                //we need to scan all the values inserted so far
                //to recompute the collision indices
                for (int i = 0; i < _freeValueCellIndex; i++)
                {
                    //get the original hash code and find the new bucketIndex
                    bucketIndex = (_valuesInfo[i].hashcode) % _buckets.Length;
                    //bucketsIndex can be -1 or a next value. If it's -1
                    //means no collisions. If there is collision, it will
                    //link to the next value index and the bucket will
                    //be updated with the current one. In this way we can
                    //rebuild the linkedlist.
                    valueIndex = GetBucketIndex(_buckets[bucketIndex]);
                    if (valueIndex != -1)
                    {
                        _collisions++;
                        _valuesInfo[i].previous      = valueIndex;
                        _valuesInfo[valueIndex].next = i;
                    }
                    else
                    {
                        _valuesInfo[i].next     = -1;
                        _valuesInfo[i].previous = -1;
                    }

                    //buckets at bucketIndex will remember the value/valueInfo
                    //index for that bucketIndex.
                    _buckets[bucketIndex] = i + 1;
                }
            }

            return(true);
        }
Exemplo n.º 4
0
        bool AddValue(TKey key, ref TValue value)
        {
            int hash        = Hash(key);
            int bucketIndex = hash % _buckets.Length;

            //buckets value -1 means it's empty
            var valueIndex = GetValueIndexFromBuckets(_buckets, bucketIndex);

            if (valueIndex == -1)
            {
                //create the info node at the last position and fill it with the relevant information
                _valuesInfo[_freeValueCellIndex] = new Node(ref key, hash);
            }
            else //collision or already exists
            {
                {
                    int currentValueIndex = valueIndex;
                    do
                    {
                        //must check if the key already exists in the dictionary
                        //for some reason this is faster than using Comparer<TKey>.default, should investigate
                        if (_valuesInfo[currentValueIndex].hashcode == hash &&
                            _valuesInfo[currentValueIndex].key.CompareTo(key) == 0)
                        {//the key already exists, simply replace the value!
                            _values[currentValueIndex] = value;
                            return(false);
                        }

                        currentValueIndex = _valuesInfo[currentValueIndex].previous;
                    }while (currentValueIndex != -1); //-1 means no more values with key with the same hash
                }

                //oops collision!
                _collisions++;
                //create a new node which previous index points to node currently pointed in the bucket
                _valuesInfo[_freeValueCellIndex] = new Node(ref key, hash, valueIndex);
                //update the next of the existing cell to point to the new one
                //old one -> new one | old one <- next one
                _valuesInfo[valueIndex].next = _freeValueCellIndex;
                //Important: the new node is always the one that will be pointed by the bucket cell
                //so I can assume that the one pointed by the bucket is always the last value added
                //(next = -1)
            }

            //item with this bucketIndex will point to the last value created
            //ToDo: if instead I assume that the original one is the one in the bucket
            //I wouldn't need to update the bucket here. Small optimization but important
            SetValueIndexInBuckets(_buckets, bucketIndex, _freeValueCellIndex);

            _values[_freeValueCellIndex] = value;

            _freeValueCellIndex++;

            if (_freeValueCellIndex == _values.Length)
            {
                Array.Resize(ref _values,
                             HashHelpers.ExpandPrime(_freeValueCellIndex));
                Array.Resize(ref _valuesInfo,
                             HashHelpers.ExpandPrime(_freeValueCellIndex));
            }

            //too many collisions?
            if (_collisions > _buckets.Length)
            {
                //we need more space and less collisions
                //ToDo: need to change from prime to Fibonacci sequence (could be quite faster)
                _buckets = new int[HashHelpers.ExpandPrime(_collisions)];

                _collisions = 0;

                //we need to get all the hash code of all the values stored so far and spread them over the new bucket
                //length
                for (int newValueIndex = 0; newValueIndex < _freeValueCellIndex; newValueIndex++)
                {
                    //get the original hash code and find the new bucketIndex due to the new length
                    bucketIndex = _valuesInfo[newValueIndex].hashcode % _buckets.Length;
                    //bucketsIndex can be -1 or a next value. If it's -1 means no collisions. If there is collision,
                    //we create a new node which prev points to the old one. Old one next points to the new one.
                    //the bucket will now points to the new one
                    //In this way we can rebuild the linkedlist.
                    //get the current valueIndex, it's -1 if no collision happens
                    int existingValueIndex = GetValueIndexFromBuckets(_buckets, bucketIndex);
                    //update the bucket index to the index of the current item that share the bucketIndex
                    //(last found is always the one in the bucket)
                    SetValueIndexInBuckets(_buckets, bucketIndex, newValueIndex);
                    if (existingValueIndex != -1)
                    {   //oops a value was already being pointed by this cell in the new bucket list,
                        //it means there is a collision, problem
                        _collisions++;
                        //the bucket will point to this value, so
                        //the previous index will be used as previous for the new value.
                        _valuesInfo[newValueIndex].previous = existingValueIndex;
                        _valuesInfo[newValueIndex].next     = -1;
                        //and update the previous next index to the new one
                        _valuesInfo[existingValueIndex].next = newValueIndex;
                    }
                    else
                    { //ok nothing was indexed, the bucket was empty. We need to update the previous
                        //values of next and previous
                        _valuesInfo[newValueIndex].next     = -1;
                        _valuesInfo[newValueIndex].previous = -1;
                    }
                }
            }

            return(true);
        }
Exemplo n.º 5
0
 private void Resize()
 {
     Resize(HashHelpers.ExpandPrime(count), forceNewHashCodes: false);
 }
Exemplo n.º 6
0
        public void TestFasterDictionary()
        {
            FasterDictionary <int, Test> test = new FasterDictionary <int, Test>();
            uint dictionarysize = 10000;

            int[] numbers = new int[dictionarysize];
            for (int i = 1; i < dictionarysize; i++)
            {
                numbers[i] = numbers[i - 1] + i * HashHelpers.ExpandPrime((int)dictionarysize);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = 0; i < dictionarysize; i += 2)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            test.Trim();

            for (int i = 0; i < dictionarysize; i++)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = 1; i < dictionarysize - 1; i += 2)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            test.Trim();

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test.Remove(i) == true)
                {
                    throw new Exception();
                }
            }

            test.Trim();

            test.Clear();
            for (int i = 0; i < dictionarysize; i++)
            {
                test[numbers[i]] = new Test(i);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                Test JapaneseCalendar = test[numbers[i]];
                if (JapaneseCalendar.i != i)
                {
                    throw new Exception("read back test failed");
                }
            }
        }
Exemplo n.º 7
0
        public void TestSveltoDictionary(int dictionarysize)
        {
            SveltoDictionary <int, Test, NativeStrategy <SveltoDictionaryNode <int> >, NativeStrategy <Test>, NativeStrategy <int> > test =
                new SveltoDictionary <int, Test, NativeStrategy <SveltoDictionaryNode <int> >, NativeStrategy <Test>, NativeStrategy <int> >(1, Allocator.Persistent);

            int[] numbers = new int[dictionarysize];

            for (int i = 1; i < dictionarysize; i++)
            {
                numbers[i] = numbers[i - 1] + i * HashHelpers.ExpandPrime((int)dictionarysize);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = 0; i < dictionarysize; i += 2)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            test.Clear();

            for (int i = 0; i < dictionarysize; i++)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = 1; i < dictionarysize - 1; i += 2)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            test.Clear();

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test.Remove(i) == true)
                {
                    throw new Exception();
                }
            }

            test.Clear();

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test.Remove(i) == false)
                {
                    throw new Exception();
                }
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                test[i] = new Test(numbers[i]);
            }

            for (int i = (int)(dictionarysize - 1); i >= 0; i -= 3)
            {
                if (test[i].i != numbers[i])
                {
                    throw new Exception();
                }
            }

            test.Clear();
            for (int i = 0; i < dictionarysize; i++)
            {
                test[numbers[i]] = new Test(i);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                Test JapaneseCalendar = test[numbers[i]];
                if (JapaneseCalendar.i != i)
                {
                    throw new Exception("read back test failed");
                }
            }

            test.Clear();

            for (int i = 0; i < dictionarysize; i++)
            {
                test[numbers[i]] = new Test(i);
            }

            for (int i = 0; i < dictionarysize; i++)
            {
                Test JapaneseCalendar = test[numbers[i]];
                if (JapaneseCalendar.i != i)
                {
                    throw new Exception("read back test failed");
                }
            }

            test.Dispose();
        }