예제 #1
0
파일: Core.cs 프로젝트: stjordanis/Imms
        /// <summary>
        ///     Inserts a sequence at the specified index, pushing the element at the index forward.
        /// </summary>
        /// <param name="index"> The index. </param>
        /// <param name="items"> The sequence of items to insert. Very fast if the sequence is also an <see cref="ImmList{T}" />.</param>
        /// <returns> </returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the index doesn't exist.</exception>
        /// <exception cref="ArgumentNullException">Thrown if the IEnumerable is null.</exception>
        public ImmList <T> InsertRange(int index, IEnumerable <T> items)
        {
            items.CheckNotNull("items");
            index.CheckIsBetween("index", -Root.Measure - 1, Root.Measure);
            index = index < 0 ? index + Length + 1 : index;
            if (index == 0)
            {
                return(AddFirstRange(items));
            }
            if (index == Root.Measure)
            {
                return(AddLastRange(items));
            }
            var list = items as ImmList <T>;

            if (list != null)
            {
                return(InsertList(index, list));
            }
            FingerTree <T> .FTree <Leaf <T> > part1, part2;

            Root.Split(index, out part1, out part2, Lineage.Immutable);
            int len;
            var i       = 0;
            var arr     = items.ToArrayFast(out len);
            var lineage = Lineage.Mutable();
            var middle  = FingerTree <T> .FTree <Leaf <T> > .Construct(arr, ref i, len, lineage);

            return(part1.AddLastList(middle, Lineage.Immutable).AddLastList(part2, Lineage.Immutable).Wrap());
        }
예제 #2
0
        /// <summary>
        ///     Provided for testing purposes only. Is too inefficient to be used in practice.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public ImmVector <T> Insert(int index, T value)
        {
            index = index < 0 ? index + Length + 1 : index;
            if (index == Length)
            {
                return(AddLast(value));
            }
            if (index == 0)
            {
                return(AddFirstRange(new[] { value }));
            }
            var lineage = Lineage.Mutable();
            var take    = Root.Take(index - 1, lineage);

            take = take.Add(value, lineage);
            var arr = new T[Length - index];

            CopyTo(arr, index, 0, Length - index);
            var len = arr.Length;
            var s   = 0;
            var ret = take.AddRange(arr, lineage, 6, ref s, ref len);

#if ASSERTS
            ret.Length.AssertEqual(Length + 1);
#endif
            return(ret);
        }
예제 #3
0
        /// <summary>
        ///     Returns the set-theoretic union between this set and a set-like collection.
        /// </summary>
        /// <param name="other">A sequence of values. This operation is much faster if it's a set compatible with this one.</param>
        /// <returns></returns>
        public override ImmSortedSet <T> Union(IEnumerable <T> other)
        {
            other.CheckNotNull("other");
            var set = other as ImmSortedSet <T>;

            if (set != null && IsCompatibleWith(set))
            {
                return(Union(set));
            }
            //this trick can't really be repeated with a non-ordered set...
            //or least I haven't figured it out yet. Basically, converts the sequence into an array, sorts it on its own
            //And then builds a tree out of it. Then it unions it with the main tree. This improves performance by a fair bit
            //Even if the data structure isn't an array already.
            int len;
            var arr = other.ToArrayFast(out len);

            Array.Sort(arr, 0, len, Comparer);
            arr.RemoveDuplicatesInSortedArray((a, b) => Comparer.Compare(a, b) == 0, ref len);
            var lineage = Lineage.Mutable();
            var node    = OrderedAvlTree <T, bool> .Node.FromSortedArraySet(arr, 0, len - 1, Comparer, lineage);

            var newRoot = node.Union(Root, null, lineage);

            return(newRoot.Wrap(Comparer));
        }
예제 #4
0
 /// <summary>
 /// removes the minimal key-value pair from this map.
 /// </summary>
 /// <returns></returns>
 public ImmSortedMap <TKey, TValue> RemoveMin()
 {
     if (Root.IsEmpty)
     {
         throw Errors.Is_empty;
     }
     return(Root.RemoveMin(Lineage.Mutable()).WrapMap(Comparer));
 }
예제 #5
0
 /// <summary>
 /// Removes the maximal element from the set.
 /// </summary>
 /// <returns></returns>
 public ImmSortedSet <T> RemoveMax()
 {
     if (Root.IsEmpty)
     {
         throw Errors.Is_empty;
     }
     return(Root.RemoveMax(Lineage.Mutable()).Wrap(Comparer));
 }
예제 #6
0
        /// <summary>
        /// Adds a new item to the set, or does nothing if the item already exists.
        /// </summary>
        /// <param name="item">The item to add.</param>
        /// <returns></returns>
        public override ImmSortedSet <T> Add(T item)
        {
            var ret = Root.Root_Add(item, true, Comparer, false, Lineage.Mutable());

            if (ret == null)
            {
                return(this);
            }
            return(ret.Wrap(Comparer));
        }
예제 #7
0
        /// <summary>
        /// Removes an item from the set, or does nothing if the item does not exist.
        /// </summary>
        /// <param name="item">The item to remove.</param>
        /// <returns></returns>
        public override ImmSortedSet <T> Remove(T item)
        {
            var ret = Root.AvlRemove(item, Lineage.Mutable());

            if (ret == null)
            {
                return(this);
            }
            return(ret.Wrap(Comparer));
        }
예제 #8
0
파일: ImmSet.cs 프로젝트: stjordanis/Imms
        /// <summary>
        /// Removes an item from the set, or does nothing if the item does not exist.
        /// </summary>
        /// <param name="item">The item to remove.</param>
        /// <returns></returns>
        public override ImmSet <T> Remove(T item)
        {
            var ret = Root.Root_Remove(item, Lineage.Mutable());

            if (ret == null)
            {
                return(this);
            }
            return(ret.Wrap(EqualityComparer));
        }
예제 #9
0
        /// <summary>
        /// Removes a key from the map, or does nothing if the key does not exist.
        /// </summary>
        /// <param name="key">The key to remove.</param>
        /// <returns></returns>
        public override ImmSortedMap <TKey, TValue> Remove(TKey key)
        {
            var removed = Root.AvlRemove(key, Lineage.Mutable());

            if (removed == null)
            {
                return(this);
            }
            return(removed.WrapMap(Comparer));
        }
예제 #10
0
파일: ImmSet.cs 프로젝트: stjordanis/Imms
        /// <summary>
        /// Adds a new item to the set, or does nothing if the item already exists.
        /// </summary>
        /// <param name="item">The item to add.</param>
        /// <returns></returns>
        public override ImmSet <T> Add(T item)
        {
            var res = Root.Root_Add(item, true, Lineage.Mutable(), EqualityComparer, false);

            if (res == null)
            {
                return(this);
            }
            return(res.Wrap(EqualityComparer));
        }
예제 #11
0
        /// <summary>
        ///     Removes the specified key from the map, or does nothing if the key doesn't exist.
        /// </summary>
        /// <param name="k">The key.</param>
        /// <returns></returns>
        public override ImmMap <TKey, TValue> Remove(TKey k)
        {
            var removed = _root.Root_Remove(k, Lineage.Mutable());

            if (removed == null)
            {
                return(this);
            }
            return(removed.WrapMap(_equality));
        }
예제 #12
0
        /// <summary>
        /// Removes several keys from this key-value map.
        /// </summary>
        /// <param name="keys">A sequence of keys to remove. Can be much faster if it's a set compatible with this map.</param>
        /// <returns></returns>
        public override ImmMap <TKey, TValue> RemoveRange(IEnumerable <TKey> keys)
        {
            keys.CheckNotNull("keys");
            var set = keys as ImmSet <TKey>;

            if (set != null && _equality.Equals(set.EqualityComparer))
            {
                return(_root.Except(set.Root, Lineage.Mutable()).WrapMap(_equality));
            }
            return(base.RemoveRange(keys));
        }
예제 #13
0
        /// <summary>
        /// Inserts a sequence of elements at the specified index.
        /// </summary>
        /// <param name="index">The index at which to insert. The element at this index is pushed forward.</param>
        /// <param name="items">The items to insert. Faster if an array or a known collection type.</param>
        /// <returns></returns>
        public ImmVector <T> InsertRange(int index, IEnumerable <T> items)
        {
            index.CheckIsBetween("index", -Root.Length - 1, Root.Length);
            items.CheckNotNull("items");
            index = index < 0 ? index + Root.Length + 1: index;
            if (index == 0)
            {
                return(AddFirstRange(items));
            }
            if (index == Length)
            {
                return(AddLastRange(items));
            }
#if ASSERTS
            var oldLast  = Last;
            var oldFirst = First;
#endif
            var start     = Root.Take(index - 1, Lineage.Immutable);
            var lineage   = Lineage.Mutable();
            var len       = 0;
            var s         = 0;
            var oldLength = Length;
            var arrInsert = items.ToArrayFast(out len);
            if (len == 0)
            {
                return(this);
            }
            var arrAfter = new T[oldLength - index];
            CopyTo(arrAfter, index, 0, oldLength - index);
            var arrLength = len;
            if (len == 0)
            {
                return(this);
            }
            if (oldLength + len >= MaxCapacity)
            {
                throw Errors.Capacity_exceeded();
            }
            start = start.AddRange(arrInsert, lineage, 6, ref s, ref len);
            len   = oldLength - index;
            s     = 0;
            start = start.AddRange(arrAfter, lineage, 6, ref s, ref len);
            ImmVector <T> ret = start;
#if ASSERTS
            ret.Length.AssertEqual(oldLength + arrLength);
            ret.RecursiveLength().AssertEqual(ret.Length);
            ret.Last.AssertEqual(oldLast);
            ret.First.AssertEqual(oldFirst);
            ret[index].AssertEqual(arrInsert[0]);
            ret[index + arrLength - 1].AssertEqual(arrInsert[arrLength - 1]);
#endif
            return(ret);
        }
예제 #14
0
        /// <summary>
        ///     Subtracts the key-value pairs in the specified map from this one, applying the subtraction function on each key shared between the maps.
        /// </summary>
        /// <param name="other">A sequence of key-value pairs. This operation is much faster if it's a map compatible with this one.</param>
        /// <param name="subtraction">Optionally, a subtraction function that generates the value in the resulting key-value map. Otherwise, key-value pairs are always removed.</param>
        /// <remarks>
        ///	Subtraction over maps is anaologous to Except over sets.
        ///	If the subtraction function is not specified (or is null), the operation simply subtracts all the keys present in the other map from this one.
        /// If a subtraction function is supplied, the operation invokes the function on each key-value pair shared with the other map. If the function returns a value,
        /// that value is used in the return map. If the function returns None, the key is removed from the return map.
        /// </remarks>
        public override ImmSortedMap <TKey, TValue> Subtract <TValue2>(IEnumerable <KeyValuePair <TKey, TValue2> > other,
                                                                       ValueSelector <TKey, TValue, TValue2, Optional <TValue> > subtraction = null)
        {
            other.CheckNotNull("other");
            var map = other as ImmSortedMap <TKey, TValue2>;

            if (map != null && Comparer.Equals(map.Comparer))
            {
                return(Root.Except(map.Root, Lineage.Mutable(), subtraction).WrapMap(Comparer));
            }
            return(base.Subtract(other, subtraction));
        }
예제 #15
0
        protected override ImmMap <TKey, TValue> Set(TKey k, TValue v, bool overwrite)
        {
            var r = _root.Root_Add(k, v, Lineage.Mutable(), _equality, overwrite);

            if (r == null && !overwrite)
            {
                throw Errors.Key_exists(k);
            }
            if (r == null)
            {
                return(this);
            }
            return(r.WrapMap(_equality));
        }
예제 #16
0
        protected override ImmSortedMap <TKey, TValue> Set(TKey key, TValue value, bool overwrite)
        {
            var ret = Root.Root_Add(key, value, Comparer, overwrite, Lineage.Mutable());

            if (ret == null && !overwrite)
            {
                throw Errors.Key_exists(key);
            }
            if (ret == null)
            {
                return(this);
            }
            return(ret.WrapMap(Comparer));
        }
예제 #17
0
파일: Core.cs 프로젝트: stjordanis/Imms
        /// <summary>
        ///     Removes the element at some index from the list.
        /// </summary>
        /// <param name="index"> The index to remove. </param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the index does not exist in the list.</exception>
        /// <returns> </returns>
        public ImmList <T> RemoveAt(int index)
        {
            index.CheckIsBetween("index", -Root.Measure, Root.Measure - 1);
            index = index < 0 ? index + Root.Measure : index;
            var ret = Root.RemoveAt(index, Lineage.Mutable()).Wrap();

#if ASSERTS
            if (Root.Measure > index + 1)
            {
                ret[index].AssertEqual(this[index + 1]);
            }
            ret.Root.Measure.AssertEqual(Root.Measure - 1);
#endif
            return(ret);
        }
예제 #18
0
파일: Core.cs 프로젝트: stjordanis/Imms
        /// <summary>
        ///     <para>Joins the specified sequence or list to the beginning of this list.</para>
        ///     <para>⚡ O(m)</para>
        /// </summary>
        /// <param name="items"> The items to add. Very fast if the sequence is also an <see cref="ImmList{T}" />.</param>
        /// <returns> </returns>
        /// <exception cref="ArgumentNullException">Thrown if the argument is null.</exception>
        public ImmList <T> AddFirstRange(IEnumerable <T> items)
        {
            items.CheckNotNull("items");
            var list = items as ImmList <T>;

            if (list != null)
            {
                return(AddFirstList(list));
            }
            var lineage = Lineage.Mutable();
            int len;
            var arr   = items.ToArrayFast(out len);
            var index = 0;
            var tree  = FingerTree <T> .FTree <Leaf <T> > .Construct(arr, ref index, len, lineage);

            return(tree.AddLastList(Root, lineage).Wrap());
        }
예제 #19
0
        /// <summary>
        ///     Copies data from an array..
        /// </summary>
        /// <param name="arr">The arr.</param>
        /// <param name="startIndex">The start index.</param>
        /// <param name="count">The count.</param>
        /// <exception cref="ArgumentNullException">Thrown if the array is null.</exception>
        /// <exception cref="InvalidOperationException">Thrown if the collection exceeds its capacity.</exception>
        private ImmVector <T> CopyFrom(T[] arr, int startIndex, int count)
        {
            arr.CheckNotNull("arr");
            startIndex.CheckIsBetween("startIndex", -arr.Length, arr.Length - 1);
            startIndex = startIndex < 0 ? arr.Length + startIndex : startIndex;
            count.CheckIsBetween("count", 0, arr.Length - startIndex);

            if (Root.Length + arr.Length >= MaxCapacity)
            {
                throw Errors.Capacity_exceeded();
            }
            var lineage = Lineage.Mutable();

            var ret = Root.AddRange(arr, lineage, 6, ref startIndex, ref count);

            return(ret);
        }
예제 #20
0
파일: Core.cs 프로젝트: stjordanis/Imms
        /// <summary>
        ///     Sets the value of the item at the specified index.
        /// </summary>
        /// <param name="index"> The index of the item to update. </param>
        /// <param name="item"> The new value of the item. </param>
        /// <returns> </returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the index doesn't exist.</exception>
        public ImmList <T> Update(int index, T item)
        {
            index.CheckIsBetween("index", -Root.Measure, Root.Measure - 1);
            index = index < 0 ? index + Root.Measure : index;
            if (index == 0)
            {
                return(RemoveFirst().AddFirst(item));
            }
            if (index == Root.Measure - 1)
            {
                return(RemoveLast().AddLast(item));
            }
            var ret = Root.Update(index, item, Lineage.Mutable()).Wrap();

            ret[index].AssertEqual(item);
            ret.Root.Measure.AssertEqual(Root.Measure);

            return(ret);
        }
예제 #21
0
파일: Core.cs 프로젝트: stjordanis/Imms
        /// <summary>
        ///     Inserts an item at the specified index, pushing the element at the index forward.
        /// </summary>
        /// <param name="index"> The index before which to insert the item.  </param>
        /// <param name="item"> The item to insert. </param>
        /// <returns> </returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the index doesn't exist.</exception>
        public ImmList <T> Insert(int index, T item)
        {
            index.CheckIsBetween("index", -Root.Measure - 1, Root.Measure);
            index = index < 0 ? Root.Measure + index + 1 : index;
            if (index == Root.Measure)
            {
                return(AddLast(item));
            }
            if (index == 0)
            {
                return(AddFirst(item));
            }
            var newRoot = Root.Insert(index, item, Lineage.Mutable());
            var ret     = newRoot.Wrap();

            ret[index].AssertEqual(item);
            ret.Root.Measure.AssertEqual(Root.Measure + 1);

            return(ret);
        }
예제 #22
0
        /// <summary>
        ///     Merges the two maps, applying the selector function for keys appearing in both maps.
        /// </summary>
        /// <param name="other">The other.</param>
        /// <param name="collision">
        ///     The collision resolution function. If null, the values in the other map overwrite the values in this map.
        /// </param>
        /// <remarks>
        /// The merge operation is analogous to a union operation over sets.
        ///
        /// This operation returns all key-value pairs present in either map. If a key is shared between both maps, the collision resolution function is applied to determine the value in the result map.
        /// </remarks>
        public override ImmSortedMap <TKey, TValue> Merge(IEnumerable <KeyValuePair <TKey, TValue> > other, ValueSelector <TKey, TValue, TValue, TValue> collision = null)
        {
            other.CheckNotNull("other");
            var map = other as ImmSortedMap <TKey, TValue>;

            if (map != null && IsCompatibleWith(map))
            {
                return(Merge(map, collision));
            }
            int len;
            var arr = other.ToArrayFast(out len);
            var cmp = Comparers.KeyComparer <KeyValuePair <TKey, TValue>, TKey>(x => x.Key, Comparer);

            Array.Sort(arr, 0, len, cmp);
            arr.RemoveDuplicatesInSortedArray((a, b) => Comparer.Compare(a.Key, b.Key) == 0, ref len);
            var lineage = Lineage.Mutable();
            var node    = OrderedAvlTree <TKey, TValue> .Node.FromSortedArray(arr, 0, len - 1, Comparer, lineage);

            var newRoot = Root.Union(node, collision, lineage);

            return(newRoot.WrapMap(Comparer));
        }
예제 #23
0
파일: Core.cs 프로젝트: stjordanis/Imms
        ImmList <T> InsertList(int index, ImmList <T> list)
        {
            index.CheckIsBetween("index", -Root.Measure - 1, Root.Measure);
            list.CheckNotNull("list");
            index = index < 0 ? Root.Measure + index + 1 : index;
            if (index == 0)
            {
                return(list.AddLastRange(this));
            }
            if (index == Root.Measure)
            {
                return(AddLastRange(list));
            }
            var lineage = Lineage.Mutable();

            FingerTree <T> .FTree <Leaf <T> > part1, part2;
            Root.Split(index, out part1, out part2, Lineage.Immutable);
            part1 = part1.AddLastList(list.Root, Lineage.Immutable);
            var result = part1.AddLastList(part2, Lineage.Immutable);

            return(result.Wrap());
        }
예제 #24
0
        /// <summary>
        ///     Provided for testing purposes only. Is too inefficient to be used in practice.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private ImmVector <T> RemoveAt(int index)
        {
            index = index < 0 ? index + Length : index;
            if (index == 0)
            {
                return(Skip(1));
            }
            if (index == Length - 1)
            {
                return(RemoveLast());
            }
            index.CheckIsBetween("index", 0, Length - 1);
            var lineage = Lineage.Mutable();
            var take    = Root.Take(index - 1, lineage);
            var arr     = new T[Length - index - 1];

            CopyTo(arr, index + 1, 0, Length - index - 1);
            var len = arr.Length;
            var s   = 0;
            var ret = take.AddRange(arr, lineage, 6, ref s, ref len);

            return(ret);
        }
예제 #25
0
        /// <summary>
        ///     Adds a sequence of items to the end of the collection.
        /// </summary>
        /// <param name="items">A sequence of items to add. Faster if the sequence is an array or a known collection type.</param>
        /// <exception cref="ArgumentNullException">Thrown if the argument is null.</exception>
        /// <exception cref="InvalidOperationException">Thrown if the collection exceeds its capacity.</exception>
        /// <remarks>This member performs a lot better when the specified sequence is an array.</remarks>
        public ImmVector <T> AddLastRange(IEnumerable <T> items)
        {
            items.CheckNotNull("items");
#if ASSERTS
            var expected = Length;
            var oldLast  = TryLast;
#endif
            var len = 0;
            var s   = 0;
            if (IsEmpty)
            {
                var asVector = items as ImmVector <T>;
                if (asVector != null)
                {
                    return(asVector);
                }
            }
            var arr    = items.ToArrayFast(out len);
            var oldLen = len;
            if (Root.Length + len >= MaxCapacity)
            {
                throw Errors.Capacity_exceeded();
            }
            ImmVector <T> ret = Root.AddRange(arr, Lineage.Mutable(), 6, ref s, ref len);
#if ASSERTS
            ret.Length.AssertEqual(expected + oldLen);
            if (arr.Length > 0 && oldLen > 0)
            {
                ret.Last.AssertEqual(arr[oldLen - 1]);
            }
            else if (oldLast.IsSome)
            {
                ret.Last.AssertEqual(oldLast.Value);
            }
#endif
            return(ret);
        }
예제 #26
0
 ImmMap <TKey, TValue> Except <TValue2>(ImmMap <TKey, TValue2> other,
                                        ValueSelector <TKey, TValue, TValue2, Optional <TValue> > subtraction = null)
 {
     other.CheckNotNull("other");
     return(_root.Except(other._root, Lineage.Mutable(), subtraction).WrapMap(_equality));
 }
예제 #27
0
 protected override ImmMap <TKey, TValue> Difference(ImmMap <TKey, TValue> other)
 {
     other.CheckNotNull("other");
     return(_root.SymDifference(other._root, Lineage.Mutable()).WrapMap(_equality));
 }
예제 #28
0
파일: ImmSet.cs 프로젝트: stjordanis/Imms
 protected override ImmSet <T> Difference(ImmSet <T> other)
 {
     return(Root.SymDifference(other.Root, Lineage.Mutable()).Wrap(EqualityComparer));
 }
예제 #29
0
파일: ImmSet.cs 프로젝트: stjordanis/Imms
 protected override ImmSet <T> Union(ImmSet <T> other)
 {
     return(Root.Union(other.Root, Lineage.Mutable()).Wrap(EqualityComparer));
 }
예제 #30
0
파일: ImmSet.cs 프로젝트: stjordanis/Imms
 protected override ImmSet <T> Intersect(ImmSet <T> other)
 {
     return(Root.Intersect(other.Root, Lineage.Mutable(), null).Wrap(EqualityComparer));
 }